diff --git a/libs/mint-intract/package.json b/libs/mint-intract/package.json new file mode 100644 index 00000000..89453d4e --- /dev/null +++ b/libs/mint-intract/package.json @@ -0,0 +1,14 @@ +{ + "name": "mint-intract", + "version": "1.0.0", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "author": "", + "license": "ISC", + "description": "", + "dependencies": { + "ethers": "^6.13.2" + } +} diff --git a/libs/mint-intract/src/index.ts b/libs/mint-intract/src/index.ts new file mode 100644 index 00000000..51e3eba1 --- /dev/null +++ b/libs/mint-intract/src/index.ts @@ -0,0 +1,2 @@ +export * from './mint-intract.module'; +export * from './mint-intract.service'; diff --git a/libs/mint-intract/src/mint-intract.module.ts b/libs/mint-intract/src/mint-intract.module.ts new file mode 100644 index 00000000..a6318778 --- /dev/null +++ b/libs/mint-intract/src/mint-intract.module.ts @@ -0,0 +1,11 @@ +import { SharedModule } from '@core/shared'; +import { Module } from '@nestjs/common'; + +import { MintIntractService } from './mint-intract.service'; + +@Module({ + imports: [SharedModule], + providers: [MintIntractService], + exports: [MintIntractService], +}) +export class MintIntractModule {} diff --git a/libs/mint-intract/src/mint-intract.service.ts b/libs/mint-intract/src/mint-intract.service.ts new file mode 100644 index 00000000..9ab354ad --- /dev/null +++ b/libs/mint-intract/src/mint-intract.service.ts @@ -0,0 +1,159 @@ +import { RegistryPlug } from '@action/registry'; +import { ChainService } from '@core/shared'; +import { Injectable } from '@nestjs/common'; +import { ConfigService } from '@nestjs/config'; +import { Contract, Interface, ethers } from 'ethers'; +import { + Action as ActionDto, + ActionMetadata, + GenerateTransactionParams, + GenerateTransactionResponse, + TransactionInfo, +} from 'src/common/dto'; +import { Chains } from 'src/constants'; + +import { FieldTypes } from './types'; + +@RegistryPlug('mint-intract', 'v1') +@Injectable() +export class MintIntractService extends ActionDto { + private readonly isDev: boolean; + constructor( + private readonly chainService: ChainService, + private readonly configService: ConfigService, + ) { + super(); + this.isDev = this.configService.get('env')! === 'dev'; + } + + async getMetadata(): Promise> { + const supportedNetwork = [ + Chains.ZkLinkNova, + Chains.ArbitrumOne, + Chains.EthereumMainnet, + Chains.Base, + Chains.Linea, + Chains.MantaPacificMainnet, + Chains.OpMainnet, + Chains.ScrollMainnet, + Chains.BSCMainnet, + ]; + if (this.isDev) { + supportedNetwork.push( + Chains.ZkLinkNovaSepolia, + Chains.ArbitrumSepolia, + Chains.BaseSepolia, + Chains.BSCTestnet, + ); + } + return { + title: 'Mint Intract NFT', + description: '
This action allows you to mint Intract NFTs
', + networks: this.chainService.buildSupportedNetworks(supportedNetwork), + author: { + name: 'Intract', + github: 'https://quest.intract.io/', + }, + magicLinkMetadata: { + title: 'Mint Intract NFT', + description: 'Mint Intract NFTs', + }, + intent: { + binding: true, + components: [ + { + name: 'contract', + label: 'NFT Contract Address', + desc: 'Enter the NFT contract address', + type: 'input', + regex: '^0x[a-fA-F0-9]{40}$', + regexDesc: 'Invalid Address', + }, + { + name: 'price', + label: 'NFT Price', + desc: 'The NFT mint fee, leave it to 0 for free mint NFT', + type: 'input', + regex: '^\\d+\\.?\\d*$|^\\d*\\.\\d+$', + regexDesc: 'Must be a number', + defaultValue: '0', + }, + ], + }, + }; + } + + async generateTransaction( + data: GenerateTransactionParams, + ): Promise { + const { additionalData, formData } = data; + const { chainId } = additionalData; + const provider = this.chainService.getProvider(chainId); + + const payable = ' payable'; + const abiParams = []; + const funcParams = []; + const txParams = []; + const recipient = additionalData.account; + abiParams.push('address _receiver'); + funcParams.push('address'); + txParams.push(recipient); + abiParams.push('uint256 _quantity'); + funcParams.push('uint256'); + txParams.push(1); + abiParams.push('address _currency'); + funcParams.push('address'); + txParams.push('0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE'); + abiParams.push('uint256 _pricePerToken'); + funcParams.push('uint256'); + txParams.push(Number(formData.price)); + abiParams.push('tuple _allowlistProof'); + funcParams.push('tuple'); + txParams.push([ + [], + 1, + Number(formData.price), + '0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE', + ]); + abiParams.push('bytes _data'); + funcParams.push('bytes'); + txParams.push([]); + + // if (formData.recipient != 'none') { + // abiParams.push('address recipient'); + // funcParams.push('address'); + // if (formData.recipient == 'sender') { + // txParams.push(additionalData.account); + // } else { + // txParams.push(formData.recipient); + // } + // } + // if (Number(formData.quantity) > 0) { + // abiParams.push('uint quantity'); + // funcParams.push('uint'); + // txParams.push(Number(formData.quantity)); + // } + // if (formData.ext != 'none') { + // abiParams.push('string ext'); + // funcParams.push('string'); + // txParams.push(formData.ext); + // } + const entrypoint = 'claim'; + const abi = new Interface([ + `function ${entrypoint}(${abiParams.join(',')})${payable}`, + ]); + + const contract = new Contract(formData.contract.toString(), abi, provider); + const mintTx = await contract[ + `${entrypoint}(${funcParams.join(',')})` + ].populateTransaction.apply(this, txParams); + const tx: TransactionInfo = { + chainId: chainId, + to: mintTx.to, + value: ethers.parseEther(formData.price).toString(), + data: mintTx.data, + shouldPublishToChain: true, + }; + return { transactions: [tx] }; + } +} diff --git a/libs/mint-intract/src/types.ts b/libs/mint-intract/src/types.ts new file mode 100644 index 00000000..624d112b --- /dev/null +++ b/libs/mint-intract/src/types.ts @@ -0,0 +1,4 @@ +export type FieldTypes = { + contract: string; + price: string; +}; diff --git a/libs/mint-intract/tsconfig.lib.json b/libs/mint-intract/tsconfig.lib.json new file mode 100644 index 00000000..befa735b --- /dev/null +++ b/libs/mint-intract/tsconfig.lib.json @@ -0,0 +1,9 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "declaration": true, + "outDir": "../../dist/libs/mint-intract" + }, + "include": ["src/**/*"], + "exclude": ["node_modules", "dist", "test", "**/*spec.ts"] +} diff --git a/libs/registry/src/registry.module.ts b/libs/registry/src/registry.module.ts index f417d435..43a9fc18 100644 --- a/libs/registry/src/registry.module.ts +++ b/libs/registry/src/registry.module.ts @@ -7,6 +7,7 @@ import { BuyNftOKXModule } from '@action/buy-nft-okx'; import { CrossChainSwapModule } from '@action/cross-chain-swap'; import { DxFunModule } from '@action/dx-fun'; import { MagicSwapModule } from '@action/magic-swap'; +import { MintIntractModule } from '@action/mint-intract'; import { MintNftModule } from '@action/mint-nft'; import { MintNovaNftModule } from '@action/mint-nova-nft'; import { NewsModule } from '@action/news'; @@ -39,6 +40,7 @@ import { RegistryService } from './registry.service'; PreSaleModule, MagicSwapModule, AgxModule, + MintIntractModule, ], providers: [RegistryService], exports: [RegistryService], diff --git a/nest-cli.json b/nest-cli.json index db032fb2..b4886d90 100644 --- a/nest-cli.json +++ b/nest-cli.json @@ -162,6 +162,15 @@ "compilerOptions": { "tsConfigPath": "libs/agx/tsconfig.lib.json" } + }, + "mint-intract": { + "type": "library", + "root": "libs/mint-intract", + "entryFile": "index", + "sourceRoot": "libs/mint-intract/src", + "compilerOptions": { + "tsConfigPath": "libs/mint-intract/tsconfig.lib.json" + } } } } \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 68bdbfee..2682e9e7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -124,6 +124,13 @@ "typescript": "^5.0.0" } }, + "libs/dx-fun": { + "version": "1.0.0", + "license": "ISC", + "dependencies": { + "ethers": "^6.13.2" + } + }, "libs/magic-swap": { "version": "1.0.0", "license": "ISC", @@ -174,6 +181,10 @@ "dotenv": "^16.4.5" } }, + "libs/okx-bridge": { + "version": "1.0.0", + "license": "ISC" + }, "libs/pump-fun": { "version": "1.0.0", "license": "ISC", @@ -7980,6 +7991,10 @@ "node": ">=0.10" } }, + "node_modules/dx-fun": { + "resolved": "libs/dx-fun", + "link": true + }, "node_modules/eastasianwidth": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", @@ -14064,6 +14079,10 @@ "integrity": "sha512-lgHwxlxV1qIg1Eap7LgIeoBWIMFibOjbrYPIPJZcI1mmGAI2m3lNYpK12Y+GBdPQ0U1hRwSord7GIaawz962qQ==", "license": "MIT" }, + "node_modules/okx-bridge": { + "resolved": "libs/okx-bridge", + "link": true + }, "node_modules/on-finished": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", diff --git a/package.json b/package.json index 0896da7e..65f22b9e 100644 --- a/package.json +++ b/package.json @@ -147,7 +147,8 @@ "^@action/magic-swap(|/.*)$": "/libs/magic-swap/src/$1", "^@action/agx(|/.*)$": "/libs/agx/src/$1", "^@action/okx-bridge(|/.*)$": "/libs/okx-bridge/src/$1", - "^@action/dx-fun(|/.*)$": "/libs/dx-fun/src/$1" + "^@action/dx-fun(|/.*)$": "/libs/dx-fun/src/$1", + "^@action/mint-intract(|/.*)$": "/libs/mint-intract/src/$1" } } -} +} \ No newline at end of file diff --git a/test/jest-e2e.json b/test/jest-e2e.json index 0394afa8..004cfcce 100644 --- a/test/jest-e2e.json +++ b/test/jest-e2e.json @@ -40,6 +40,8 @@ "@action/magic-swap/(.*)": "/../libs/magic-swap/src/$1", "@action/magic-swap": "/../libs/magic-swap/src", "@action/agx/(.*)": "/../libs/agx/src/$1", - "@action/agx": "/../libs/agx/src" + "@action/agx": "/../libs/agx/src", + "@action/mint-intract/(.*)": "/../libs/mint-intract/src/$1", + "@action/mint-intract": "/../libs/mint-intract/src" } } diff --git a/tsconfig.json b/tsconfig.json index 5396c518..8e263964 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -143,6 +143,12 @@ ], "@action/agx/*": [ "libs/agx/src/*" + ], + "@action/mint-intract": [ + "libs/mint-intract/src" + ], + "@action/mint-intract/*": [ + "libs/mint-intract/src/*" ] } }