Comparing version 1.0.3 to 1.0.4
@@ -23,3 +23,5 @@ "use strict"; | ||
async mint(baseUrl, recipients, uploadToIndexer = true) { | ||
const deployment = await this.factory.deploy(); | ||
const deployment = await this.factory.deploy({ | ||
gasLimit: 3000000 | ||
}); | ||
return await this.mintToExisting(deployment.address, baseUrl, recipients, uploadToIndexer); | ||
@@ -50,3 +52,5 @@ } | ||
const contract = this.factory.attach(contractAddress); | ||
const transaction = await contract.mint(baseUrl, amount, merkleRootString, merkleRootString, depth); | ||
const transaction = await contract.mint(baseUrl, amount, merkleRootString, merkleRootString, depth, { | ||
gasLimit: 200000 | ||
}); | ||
const receipt = await transaction.wait(); | ||
@@ -53,0 +57,0 @@ if (receipt.status === 0) |
@@ -39,2 +39,12 @@ /// <reference types="node" /> | ||
* | ||
* @param tokenIndex | ||
* @parma verify | ||
*/ | ||
getTokensData(tokenIndex: number[], verify?: boolean): Promise<{ | ||
data: cNFTData; | ||
proof: Buffer; | ||
}[]>; | ||
/** | ||
* Call indexer to fetch owned tokens | ||
* | ||
* @param address | ||
@@ -52,2 +62,6 @@ * @param verify | ||
transfer(tokenIndex: number, recipient: string): Promise<string>; | ||
transferBatch(dst: { | ||
index: number; | ||
recipient: string; | ||
}[]): Promise<any>; | ||
} |
@@ -50,2 +50,29 @@ "use strict"; | ||
* | ||
* @param tokenIndex | ||
* @parma verify | ||
*/ | ||
async getTokensData(tokenIndex, verify) { | ||
const resp = await fetch(this.client.indexerUrl + "/" + this.contractAddress + "/tokens?indexes=" + encodeURIComponent(tokenIndex.join(","))); | ||
if (!resp.ok) | ||
throw new Error("Indexer error: " + await resp.text()); | ||
const obj = await resp.json(); | ||
//TODO: This doesn't check the correctness of the returned token data (correct indices returned) | ||
for (let tokenData of obj) { | ||
if (!await this.verifyTokenOwnership(tokenData.owner, tokenData.index, Buffer.from(tokenData.proof, "hex"))) | ||
throw new Error("Token ownership verification error!"); | ||
} | ||
return obj.map(tokenData => { | ||
return { | ||
proof: Buffer.from(tokenData.proof, "hex"), | ||
data: { | ||
owner: tokenData.owner, | ||
index: tokenData.index, | ||
url: this.getNftUrl(tokenData.index) | ||
} | ||
}; | ||
}); | ||
} | ||
/** | ||
* Call indexer to fetch owned tokens | ||
* | ||
* @param address | ||
@@ -108,16 +135,36 @@ * @param verify | ||
throw new Error("Token not owned by signer!"); | ||
const transaction = await this.contract.transfer(tokenIndex, recipient, "0x" + data.proof.toString("hex")); | ||
const transaction = await this.contract.transfer(tokenIndex, recipient, "0x" + data.proof.toString("hex"), { | ||
gasLimit: 100000 | ||
}); | ||
const receipt = await transaction.wait(); | ||
if (receipt.status === 0) | ||
throw new Error("Transfer transaction failed"); | ||
// transaction.chainId = await this.client.signer.getChainId(); | ||
// transaction.gasLimit = BigNumber.from(80000); | ||
// transaction.gasPrice = await this.client.signer.getGasPrice(); | ||
// transaction.nonce = await this.client.signer.getTransactionCount(signerAddress); | ||
// | ||
// const submittedTx = await this.client.signer.sendTransaction(transaction); | ||
// const receipt = await submittedTx.wait(); | ||
return receipt.transactionHash; | ||
} | ||
async transferBatch(dst) { | ||
if (dst.length > 6) | ||
throw new Error("Max num of transfers is 6!"); | ||
const allTokens = await this.getAllTokens(true); | ||
const signerAddress = await this.client.signer.getAddress(); | ||
const indexes = []; | ||
const addresses = []; | ||
const proofs = []; | ||
for (let destination of dst) { | ||
if (allTokens[destination.index].owner != signerAddress) | ||
throw new Error("Token not owned by signer!"); | ||
const merkleTree = (0, Utils_1.createMerkleTree)(this.contractData.depth, allTokens.map(token => Buffer.from(token.owner.substring(2), "hex"))); | ||
indexes.push(destination.index); | ||
addresses.push(destination.recipient); | ||
proofs.push(Buffer.concat((0, Utils_1.getMerkleProof)(merkleTree, destination.index))); | ||
allTokens[destination.index].owner = destination.recipient; | ||
} | ||
const transaction = await this.contract.transferBatch(indexes, addresses, "0x" + Buffer.concat(proofs).toString("hex"), { | ||
gasLimit: 200000 | ||
}); | ||
const receipt = await transaction.wait(); | ||
if (receipt.status === 0) | ||
throw new Error("Transfer transaction failed"); | ||
return receipt.transactionHash; | ||
} | ||
} | ||
exports.cNFTCollection = cNFTCollection; |
@@ -6,5 +6,4 @@ "use strict"; | ||
const crypto_1 = require("crypto"); | ||
const fs = require("fs"); | ||
const privateKey = "05acf48110ffce4b15251b4c0e863c1082954330057561acf956e6ce89e1359d"; | ||
const provider = new ethers_1.providers.JsonRpcProvider("https://sepolia.infura.io/v3/dcc43582332146c8b223e180181247c7"); | ||
const provider = new ethers_1.providers.JsonRpcProvider("https://alien-virulent-research.ethereum-sepolia.quiknode.pro/c7e739b4e5bbdc523f0b5b7352ae73c42bec7adc/"); | ||
const signer = new ethers_1.Wallet(privateKey, provider); | ||
@@ -14,3 +13,3 @@ async function main() { | ||
console.log("Signer address: ", walletAddress); | ||
const client = new cNFTClient_1.cNFTClient(signer, "http://localhost:3000/"); | ||
const client = new cNFTClient_1.cNFTClient(signer, "http://localhost:4000"); | ||
const recipients = []; | ||
@@ -20,7 +19,8 @@ for (let i = 0; i < 10000; i++) { | ||
} | ||
recipients[0] = walletAddress; | ||
for (let i = 0; i < 100; i++) { | ||
recipients[i] = walletAddress; | ||
} | ||
console.log("Minting nft collection..."); | ||
const nftCollection = await client.mintToExisting("0xf1c024f29af37871e4014f585e2486f140f5ef6e", "https://example.com/{INDEX}.jpg", recipients, false); | ||
const nftCollection = await client.mint("http://localhost:3000/nfts/{INDEX}.jpg", recipients, false); | ||
console.log("NFT collection minted: ", nftCollection.contractAddress); | ||
fs.writeFileSync(nftCollection.contractAddress + ".json", JSON.stringify(recipients)); | ||
} | ||
@@ -30,6 +30,20 @@ async function main2() { | ||
console.log("Signer address: ", walletAddress); | ||
const client = new cNFTClient_1.cNFTClient(signer, "http://localhost:3000/"); | ||
const client = new cNFTClient_1.cNFTClient(signer, "http://localhost:4000"); | ||
const nftCollection = await client.load("0xf1c024f29af37871e4014f585e2486f140f5ef6e"); | ||
console.log("NFT collection loaded: ", nftCollection.contractAddress); | ||
const tokenData = await nftCollection.getTokenData(10); | ||
console.log("Token data: ", tokenData); | ||
} | ||
async function main3() { | ||
const walletAddress = await signer.getAddress(); | ||
console.log("Signer address: ", walletAddress); | ||
const client = new cNFTClient_1.cNFTClient(signer, "http://localhost:4000"); | ||
const dst = "0xdfe77057d88bbd5308056da6d6361c462b61a98e"; | ||
const nftCollection = await client.load("0xf1c024f29af37871e4014f585e2486f140f5ef6e"); | ||
console.log("Transfer started..."); | ||
const txId = await nftCollection.transfer(0, dst); | ||
console.log("NFT transferred, txId: ", txId); | ||
} | ||
async function main4() { | ||
} | ||
main().catch(e => console.error(e)); |
/// <reference types="node" /> | ||
export declare function createMerkleTree(depth: number, leafs: Buffer[]): Buffer[][]; | ||
export declare function getMerkleProof(merkleTree: Buffer[][], proofIndex: number): Buffer[]; | ||
export declare function getMerkleRoot(depth: number, leafs: Buffer[]): Buffer; |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.getMerkleRoot = exports.createMerkleTree = void 0; | ||
exports.getMerkleRoot = exports.getMerkleProof = exports.createMerkleTree = void 0; | ||
const ethers_1 = require("ethers"); | ||
@@ -36,2 +36,13 @@ function createMerkleTree(depth, leafs) { | ||
exports.createMerkleTree = createMerkleTree; | ||
function getMerkleProof(merkleTree, proofIndex) { | ||
const proof = Array(merkleTree.length - 1); | ||
for (let layerIndex = 0; layerIndex < merkleTree.length - 1; layerIndex++) { | ||
const position = proofIndex & 0b1; //0 - left, 1 - right | ||
const layer = merkleTree[layerIndex]; | ||
proof[layerIndex] = position === 0 ? layer[proofIndex + 1] : layer[proofIndex - 1]; | ||
proofIndex = proofIndex >> 1; | ||
} | ||
return proof; | ||
} | ||
exports.getMerkleProof = getMerkleProof; | ||
function getMerkleRoot(depth, leafs) { | ||
@@ -38,0 +49,0 @@ const merkleTree = createMerkleTree(depth, leafs); |
{ | ||
"name": "cnftevm", | ||
"version": "1.0.3", | ||
"version": "1.0.4", | ||
"description": "", | ||
@@ -5,0 +5,0 @@ "author": "", |
@@ -28,3 +28,5 @@ import {ContractFactory, Signer, providers, BigNumber} from "ethers"; | ||
async mint(baseUrl: string, recipients: string[], uploadToIndexer: boolean = true): Promise<cNFTCollection> { | ||
const deployment = await this.factory.deploy(); | ||
const deployment = await this.factory.deploy({ | ||
gasLimit: 3000000 | ||
}); | ||
@@ -62,3 +64,5 @@ return await this.mintToExisting(deployment.address, baseUrl, recipients, uploadToIndexer); | ||
const transaction = await contract.mint(baseUrl, amount, merkleRootString, merkleRootString, depth); | ||
const transaction = await contract.mint(baseUrl, amount, merkleRootString, merkleRootString, depth, { | ||
gasLimit: 200000 | ||
}); | ||
@@ -65,0 +69,0 @@ const receipt = await transaction.wait(); |
@@ -5,3 +5,3 @@ import {BigNumber, Contract, UnsignedTransaction} from "ethers"; | ||
import {cNFTClient} from "./cNFTClient"; | ||
import {getMerkleRoot} from "./Utils"; | ||
import {createMerkleTree, getMerkleProof, getMerkleRoot} from "./Utils"; | ||
@@ -86,2 +86,39 @@ export type cNFTData = { | ||
* | ||
* @param tokenIndex | ||
* @parma verify | ||
*/ | ||
async getTokensData(tokenIndex: number[], verify?: boolean): Promise<{ | ||
data: cNFTData, | ||
proof: Buffer | ||
}[]> { | ||
const resp = await fetch(this.client.indexerUrl+"/"+this.contractAddress+"/tokens?indexes="+encodeURIComponent(tokenIndex.join(","))); | ||
if(!resp.ok) throw new Error("Indexer error: "+await resp.text()); | ||
const obj: { | ||
index: number, | ||
proof: string, | ||
owner: string | ||
}[] = await resp.json(); | ||
//TODO: This doesn't check the correctness of the returned token data (correct indices returned) | ||
for(let tokenData of obj) { | ||
if(!await this.verifyTokenOwnership(tokenData.owner, tokenData.index, Buffer.from(tokenData.proof, "hex"))) throw new Error("Token ownership verification error!"); | ||
} | ||
return obj.map(tokenData => { | ||
return { | ||
proof: Buffer.from(tokenData.proof, "hex"), | ||
data: { | ||
owner: tokenData.owner, | ||
index: tokenData.index, | ||
url: this.getNftUrl(tokenData.index) | ||
} | ||
} | ||
}); | ||
} | ||
/** | ||
* Call indexer to fetch owned tokens | ||
* | ||
* @param address | ||
@@ -161,3 +198,5 @@ * @param verify | ||
const transaction = await this.contract.transfer(tokenIndex, recipient, "0x"+data.proof.toString("hex")); | ||
const transaction = await this.contract.transfer(tokenIndex, recipient, "0x"+data.proof.toString("hex"), { | ||
gasLimit: 100000 | ||
}); | ||
@@ -167,10 +206,34 @@ const receipt = await transaction.wait(); | ||
// transaction.chainId = await this.client.signer.getChainId(); | ||
// transaction.gasLimit = BigNumber.from(80000); | ||
// transaction.gasPrice = await this.client.signer.getGasPrice(); | ||
// transaction.nonce = await this.client.signer.getTransactionCount(signerAddress); | ||
// | ||
// const submittedTx = await this.client.signer.sendTransaction(transaction); | ||
// const receipt = await submittedTx.wait(); | ||
return receipt.transactionHash; | ||
} | ||
async transferBatch(dst: { | ||
index: number, | ||
recipient: string | ||
}[]) { | ||
if(dst.length>6) throw new Error("Max num of transfers is 6!"); | ||
const allTokens = await this.getAllTokens(true); | ||
const signerAddress = await this.client.signer.getAddress(); | ||
const indexes: number[] = []; | ||
const addresses: string[] = []; | ||
const proofs: Buffer[] = []; | ||
for(let destination of dst) { | ||
if(allTokens[destination.index].owner!=signerAddress) throw new Error("Token not owned by signer!"); | ||
const merkleTree = createMerkleTree(this.contractData.depth, allTokens.map(token => Buffer.from(token.owner.substring(2), "hex"))); | ||
indexes.push(destination.index); | ||
addresses.push(destination.recipient); | ||
proofs.push(Buffer.concat(getMerkleProof(merkleTree, destination.index))); | ||
allTokens[destination.index].owner = destination.recipient; | ||
} | ||
const transaction = await this.contract.transferBatch(indexes, addresses, "0x"+Buffer.concat(proofs).toString("hex"), { | ||
gasLimit: 200000 | ||
}); | ||
const receipt = await transaction.wait(); | ||
if (receipt.status === 0) throw new Error("Transfer transaction failed"); | ||
return receipt.transactionHash; | ||
@@ -177,0 +240,0 @@ } |
@@ -8,3 +8,3 @@ import {cNFTClient} from "./cNFTClient"; | ||
const provider = new providers.JsonRpcProvider("https://sepolia.infura.io/v3/dcc43582332146c8b223e180181247c7"); | ||
const provider = new providers.JsonRpcProvider("https://alien-virulent-research.ethereum-sepolia.quiknode.pro/c7e739b4e5bbdc523f0b5b7352ae73c42bec7adc/"); | ||
const signer = new Wallet(privateKey, provider); | ||
@@ -16,3 +16,3 @@ | ||
const client = new cNFTClient(signer, "http://localhost:3000/"); | ||
const client = new cNFTClient(signer, "http://localhost:4000"); | ||
@@ -23,11 +23,11 @@ const recipients: string[] = []; | ||
} | ||
recipients[0] = walletAddress; | ||
for(let i=0;i<100;i++) { | ||
recipients[i] = walletAddress; | ||
} | ||
console.log("Minting nft collection..."); | ||
const nftCollection = await client.mintToExisting("0xf1c024f29af37871e4014f585e2486f140f5ef6e", "https://example.com/{INDEX}.jpg", recipients, false); | ||
const nftCollection = await client.mint("http://localhost:3000/nfts/{INDEX}.jpg", recipients, false); | ||
console.log("NFT collection minted: ", nftCollection.contractAddress); | ||
fs.writeFileSync(nftCollection.contractAddress+".json", JSON.stringify(recipients)); | ||
} | ||
@@ -39,3 +39,3 @@ | ||
const client = new cNFTClient(signer, "http://localhost:3000/"); | ||
const client = new cNFTClient(signer, "http://localhost:4000"); | ||
@@ -45,6 +45,26 @@ const nftCollection = await client.load("0xf1c024f29af37871e4014f585e2486f140f5ef6e"); | ||
console.log("NFT collection loaded: ", nftCollection.contractAddress); | ||
const tokenData = await nftCollection.getTokenData(10); | ||
console.log("Token data: ", tokenData); | ||
} | ||
main().catch(e => console.error(e)); | ||
async function main3() { | ||
const walletAddress = await signer.getAddress(); | ||
console.log("Signer address: ", walletAddress); | ||
const client = new cNFTClient(signer, "http://localhost:4000"); | ||
const dst = "0xdfe77057d88bbd5308056da6d6361c462b61a98e"; | ||
const nftCollection = await client.load("0xf1c024f29af37871e4014f585e2486f140f5ef6e"); | ||
console.log("Transfer started..."); | ||
const txId = await nftCollection.transfer(0, dst); | ||
console.log("NFT transferred, txId: ", txId); | ||
} | ||
async function main4() { | ||
} | ||
main().catch(e => console.error(e)); |
@@ -43,2 +43,19 @@ import {utils} from "ethers"; | ||
export function getMerkleProof(merkleTree: Buffer[][], proofIndex: number): Buffer[] { | ||
const proof: Buffer[] = Array(merkleTree.length-1); | ||
for(let layerIndex = 0; layerIndex<merkleTree.length-1; layerIndex++) { | ||
const position = proofIndex & 0b1; //0 - left, 1 - right | ||
const layer = merkleTree[layerIndex]; | ||
proof[layerIndex] = position===0 ? layer[proofIndex+1] : layer[proofIndex-1]; | ||
proofIndex = proofIndex >> 1; | ||
} | ||
return proof; | ||
} | ||
export function getMerkleRoot(depth: number, leafs: Buffer[]): Buffer { | ||
@@ -45,0 +62,0 @@ const merkleTree = createMerkleTree(depth, leafs); |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Found 1 instance in 1 package
127958
2595
1
5