From ca3f5967c2c568289cb7620b50f2f45b2c61ee2c Mon Sep 17 00:00:00 2001 From: KarishmaBothara Date: Mon, 11 Sep 2023 11:37:04 +0400 Subject: [PATCH 1/4] Test to check max payment and max fee per gas when doing fee proxy callWithFeePreference with evm call --- .../use-feeProxy/src/feeProxyWithEVMCall.ts | 73 +++++++++++++++++++ 1 file changed, 73 insertions(+) create mode 100644 examples/substrate/use-feeProxy/src/feeProxyWithEVMCall.ts diff --git a/examples/substrate/use-feeProxy/src/feeProxyWithEVMCall.ts b/examples/substrate/use-feeProxy/src/feeProxyWithEVMCall.ts new file mode 100644 index 0000000..23103f9 --- /dev/null +++ b/examples/substrate/use-feeProxy/src/feeProxyWithEVMCall.ts @@ -0,0 +1,73 @@ +import { collectArgs } from "@trne/utils/collectArgs"; +import { createKeyring } from "@trne/utils/createKeyring"; +import { filterExtrinsicEvents } from "@trne/utils/filterExtrinsicEvents"; +import { getChainApi } from "@trne/utils/getChainApi"; +import { ERC20_ABI, getERC20PrecompileForAssetId } from "@trne/utils/getERC20PrecompileAddress"; +import { sendExtrinsic } from "@trne/utils/sendExtrinsic"; +import assert from "assert"; +import { cleanEnv, str } from "envalid"; +import { utils } from "ethers"; +import { getDefaultProvider } from "ethers"; + +const argv = collectArgs(); + +const env = cleanEnv(process.env, { + CALLER_PRIVATE_KEY: str(), // private key of extrinsic caller +}); + +// This example assumes, there is liquidity pool for paymentAsset[1124] AND XrpAsset (100,000,000,000 & 100,000,000,000) +export async function main() { + assert("paymentAsset" in argv, "Payment asset ID is required"); + + const api = await getChainApi("local"); + const caller = createKeyring(env.CALLER_PRIVATE_KEY); + const { paymentAsset } = argv as unknown as { paymentAsset: number }; + const { erc20Precompile } = getERC20PrecompileForAssetId(env.CALLER_PRIVATE_KEY, paymentAsset); + const provider = getDefaultProvider("ws://127.0.0.1:9944"); + const fees = await provider.getFeeData(); + console.log("fees::", fees.maxFeePerGas?.toString()); + const sender = caller.address; + const value = 0; //eth + const gasLimit = 22953; + const maxFeePerGas = fees.maxFeePerGas?.toNumber(); //30001500000000 + const maxPriorityFeePerGas = null; + const nonce = null; + const accessList = null; + const transferAmount = 1; + const iface = new utils.Interface(ERC20_ABI); + const BOB = "0x25451A4de12dcCc2D166922fA938E900fCc4ED24"; + const encodedInput = iface.encodeFunctionData("transfer", [BOB, transferAmount]); + + const evmCall = api.tx.evm.call( + sender, + erc20Precompile.address, + encodedInput, + value, + gasLimit, + maxFeePerGas, + maxPriorityFeePerGas, + nonce, + accessList + ); + + const maxPayment = 3000150; + const feeProxiedCall = api.tx.feeProxy.callWithFeePreferences(paymentAsset, maxPayment, evmCall); + const { result } = await sendExtrinsic(feeProxiedCall, caller, { + log: console, + }); + + const [proxyEvent, evmEvent] = filterExtrinsicEvents(result.events, [ + "FeeProxy.CallWithFeePreferences", + // depending on what extrinsic call you have, filter out the right event here + "Evm.Log", + ]); + console.log("Extrinsic Result", { + proxy: proxyEvent.toJSON(), + evmEvent: evmEvent.toJSON(), + }); + + await api.disconnect(); + process.exit(0); +} + +main(); From 9902ff14b5730da04ed804a694cbc216cb0ccf19 Mon Sep 17 00:00:00 2001 From: KarishmaBothara Date: Wed, 8 Nov 2023 17:26:32 +0400 Subject: [PATCH 2/4] Enable public minting and public mint example --- examples/substrate/use-sft/README.md | 3 + examples/substrate/use-sft/package.json | 4 +- .../substrate/use-sft/src/enablePublicMint.ts | 78 +++++++++++++++++++ examples/substrate/use-sft/src/publicMint.ts | 47 +++++++++++ 4 files changed, 131 insertions(+), 1 deletion(-) create mode 100644 examples/substrate/use-sft/src/enablePublicMint.ts create mode 100644 examples/substrate/use-sft/src/publicMint.ts diff --git a/examples/substrate/use-sft/README.md b/examples/substrate/use-sft/README.md index 60c21f3..6580917 100644 --- a/examples/substrate/use-sft/README.md +++ b/examples/substrate/use-sft/README.md @@ -34,4 +34,7 @@ pnpm call:mint # transfer tokens(s) pnpm call:transfer +# enable public minting +pnpm call:enablePublicMint + ``` diff --git a/examples/substrate/use-sft/package.json b/examples/substrate/use-sft/package.json index 3b52d68..acbd023 100644 --- a/examples/substrate/use-sft/package.json +++ b/examples/substrate/use-sft/package.json @@ -6,6 +6,8 @@ "call:createToken": "pnpm call src/createToken.ts", "call:updateToken": "pnpm call src/updateToken.ts", "call:mint": "pnpm call src/mint.ts", - "call:transfer": "pnpm call src/transfer.ts" + "call:transfer": "pnpm call src/transfer.ts", + "call:enablePublicMint": "pnpm call src/enablePublicMint.ts", + "call:publicMint": "pnpm call src/publicMint.ts" } } diff --git a/examples/substrate/use-sft/src/enablePublicMint.ts b/examples/substrate/use-sft/src/enablePublicMint.ts new file mode 100644 index 0000000..a79e2a4 --- /dev/null +++ b/examples/substrate/use-sft/src/enablePublicMint.ts @@ -0,0 +1,78 @@ +import { filterExtrinsicEvents } from "@trne/utils/filterExtrinsicEvents"; +import { formatEventData } from "@trne/utils/formatEventData"; +import { sendExtrinsic } from "@trne/utils/sendExtrinsic"; +import { withChainApi } from "@trne/utils/withChainApi"; + +const COLLECTION_ID = 1124; +const TOKEN_ID = 0; + +/** + * Assuming a collection and a new token for a collection is created. + * + * Assumes the caller has XRP to pay for gas. + */ +withChainApi("local", async (api, caller, logger) => { + const tokenId = [COLLECTION_ID, TOKEN_ID] as [number, number]; + const enabled = true; + + logger.info( + { + parameters: { + tokenId, + enabled, + }, + }, + `create a "sft.togglePublicMint" extrinsic` + ); + + let extrinsic = api.tx.sft.togglePublicMint(tokenId, enabled); + + logger.info(`dispatch extrinsic from caller/owner="${caller.address}"`); + let { result, extrinsicId } = await sendExtrinsic(extrinsic, caller, { log: logger }); + let [createEvent] = filterExtrinsicEvents(result.events, ["Sft.PublicMintToggle"]); + + logger.info( + { + result: { + extrinsicId, + blockNumber: result.blockNumber, + createEvent: formatEventData(createEvent.event), + }, + }, + "receive result" + ); + + // set mint fee for public minting + + const paymentAsset = 2; + const price = 100; + const pricingDetails = [paymentAsset, price]; + logger.info( + { + parameters: { + tokenId, + pricingDetails, + }, + }, + `create a "sft.togglePublicMint" extrinsic` + ); + + extrinsic = api.tx.sft.setMintFee(tokenId, pricingDetails); + + logger.info(`dispatch extrinsic from caller/owner="${caller.address}"`); + const response = await sendExtrinsic(extrinsic, caller, { log: logger }); + result = response.result; + extrinsicId = response.extrinsicId; + [createEvent] = filterExtrinsicEvents(result.events, ["Sft.MintPriceSet"]); + + logger.info( + { + result: { + extrinsicId, + blockNumber: result.blockNumber, + createEvent: formatEventData(createEvent.event), + }, + }, + "receive result" + ); +}); diff --git a/examples/substrate/use-sft/src/publicMint.ts b/examples/substrate/use-sft/src/publicMint.ts new file mode 100644 index 0000000..c796ef8 --- /dev/null +++ b/examples/substrate/use-sft/src/publicMint.ts @@ -0,0 +1,47 @@ +import { filterExtrinsicEvents } from "@trne/utils/filterExtrinsicEvents"; +import { formatEventData } from "@trne/utils/formatEventData"; +import { sendExtrinsic } from "@trne/utils/sendExtrinsic"; +import { withChainApi } from "@trne/utils/withChainApi"; + +const COLLECTION_ID = 1124; +const TOKEN_ID = 0; + +/** + * Assuming a collection, a new token for a collection is created and togglePublicMint is enabled for this (collection, tokenId) combination + * + * Assumes the caller has XRP to pay for gas and caller is not the collection owner. + */ +withChainApi("local", async (api, caller, logger) => { + const collectionId = COLLECTION_ID; + const tokenId = TOKEN_ID; + const tokenOwner = caller.address; + const quantity = 10; + const serialNumbers = [[tokenId, quantity]] as unknown as [[number, number]]; + + logger.info( + { + parameters: { + collectionId, + serialNumbers, + tokenOwner, + }, + }, + `create a "sft.mint" extrinsic` + ); + const extrinsic = api.tx.sft.mint(collectionId, serialNumbers, tokenOwner); + + logger.info(`dispatch extrinsic from caller="${caller.address}"`); + const { result, extrinsicId } = await sendExtrinsic(extrinsic, caller, { log: logger }); + const [mintFeePaidEvent] = filterExtrinsicEvents(result.events, ["Sft.MintFeePaid"]); + + logger.info( + { + result: { + extrinsicId, + blockNumber: result.blockNumber, + mintEvent: formatEventData(mintFeePaidEvent.event), + }, + }, + "receive result" + ); +}); From c87323d4ebaf24d46d450c4abb7f4d870194c946 Mon Sep 17 00:00:00 2001 From: KarishmaBothara Date: Thu, 9 Nov 2023 07:17:01 +0400 Subject: [PATCH 3/4] Remove unwanted file --- .../use-feeProxy/src/feeProxyWithEVMCall.ts | 73 ------------------- 1 file changed, 73 deletions(-) delete mode 100644 examples/substrate/use-feeProxy/src/feeProxyWithEVMCall.ts diff --git a/examples/substrate/use-feeProxy/src/feeProxyWithEVMCall.ts b/examples/substrate/use-feeProxy/src/feeProxyWithEVMCall.ts deleted file mode 100644 index 23103f9..0000000 --- a/examples/substrate/use-feeProxy/src/feeProxyWithEVMCall.ts +++ /dev/null @@ -1,73 +0,0 @@ -import { collectArgs } from "@trne/utils/collectArgs"; -import { createKeyring } from "@trne/utils/createKeyring"; -import { filterExtrinsicEvents } from "@trne/utils/filterExtrinsicEvents"; -import { getChainApi } from "@trne/utils/getChainApi"; -import { ERC20_ABI, getERC20PrecompileForAssetId } from "@trne/utils/getERC20PrecompileAddress"; -import { sendExtrinsic } from "@trne/utils/sendExtrinsic"; -import assert from "assert"; -import { cleanEnv, str } from "envalid"; -import { utils } from "ethers"; -import { getDefaultProvider } from "ethers"; - -const argv = collectArgs(); - -const env = cleanEnv(process.env, { - CALLER_PRIVATE_KEY: str(), // private key of extrinsic caller -}); - -// This example assumes, there is liquidity pool for paymentAsset[1124] AND XrpAsset (100,000,000,000 & 100,000,000,000) -export async function main() { - assert("paymentAsset" in argv, "Payment asset ID is required"); - - const api = await getChainApi("local"); - const caller = createKeyring(env.CALLER_PRIVATE_KEY); - const { paymentAsset } = argv as unknown as { paymentAsset: number }; - const { erc20Precompile } = getERC20PrecompileForAssetId(env.CALLER_PRIVATE_KEY, paymentAsset); - const provider = getDefaultProvider("ws://127.0.0.1:9944"); - const fees = await provider.getFeeData(); - console.log("fees::", fees.maxFeePerGas?.toString()); - const sender = caller.address; - const value = 0; //eth - const gasLimit = 22953; - const maxFeePerGas = fees.maxFeePerGas?.toNumber(); //30001500000000 - const maxPriorityFeePerGas = null; - const nonce = null; - const accessList = null; - const transferAmount = 1; - const iface = new utils.Interface(ERC20_ABI); - const BOB = "0x25451A4de12dcCc2D166922fA938E900fCc4ED24"; - const encodedInput = iface.encodeFunctionData("transfer", [BOB, transferAmount]); - - const evmCall = api.tx.evm.call( - sender, - erc20Precompile.address, - encodedInput, - value, - gasLimit, - maxFeePerGas, - maxPriorityFeePerGas, - nonce, - accessList - ); - - const maxPayment = 3000150; - const feeProxiedCall = api.tx.feeProxy.callWithFeePreferences(paymentAsset, maxPayment, evmCall); - const { result } = await sendExtrinsic(feeProxiedCall, caller, { - log: console, - }); - - const [proxyEvent, evmEvent] = filterExtrinsicEvents(result.events, [ - "FeeProxy.CallWithFeePreferences", - // depending on what extrinsic call you have, filter out the right event here - "Evm.Log", - ]); - console.log("Extrinsic Result", { - proxy: proxyEvent.toJSON(), - evmEvent: evmEvent.toJSON(), - }); - - await api.disconnect(); - process.exit(0); -} - -main(); From fb3cea22fd2f3ed6b258cd5672b5c219528477c7 Mon Sep 17 00:00:00 2001 From: KarishmaBothara Date: Thu, 9 Nov 2023 07:19:44 +0400 Subject: [PATCH 4/4] Update readme --- examples/substrate/use-sft/README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/examples/substrate/use-sft/README.md b/examples/substrate/use-sft/README.md index 6580917..581570c 100644 --- a/examples/substrate/use-sft/README.md +++ b/examples/substrate/use-sft/README.md @@ -37,4 +37,7 @@ pnpm call:transfer # enable public minting pnpm call:enablePublicMint +# public minting +pnpm call:publicMint + ```