From f97a8556c85234c074fe7e89232defd06798bcbe Mon Sep 17 00:00:00 2001 From: Halil Beycan <50718965+BeycanDeveloper@users.noreply.github.com> Date: Mon, 18 Mar 2024 23:08:23 +0800 Subject: [PATCH 001/114] Added promise types for assets --- packages/types/src/assets.ts | 26 ++++++++++++------- .../services/TransactionSignerInterface.ts | 2 +- 2 files changed, 18 insertions(+), 10 deletions(-) diff --git a/packages/types/src/assets.ts b/packages/types/src/assets.ts index c4b866f..f321cbe 100644 --- a/packages/types/src/assets.ts +++ b/packages/types/src/assets.ts @@ -48,7 +48,7 @@ export interface AssetInterface { * @param owner Address of the wallet * @returns Wallet balance as currency of TOKEN or COIN assets */ - getBalance: (owner: string) => number + getBalance: (owner: string) => Promise /** * transfer() method is the main method for processing transfers for fungible assets (TOKEN, COIN) @@ -56,7 +56,11 @@ export interface AssetInterface { * @param receiver Receiver wallet address * @param amount Amount of assets that will be transferred */ - transfer: (sender: string, receiver: string, amount: number) => TransactionSignerInterface + transfer: ( + sender: string, + receiver: string, + amount: number + ) => Promise } // Sub Interfaces @@ -71,12 +75,12 @@ export interface TokenInterface extends AssetInterface, ContractInterface { /** * @returns Decimal value of the token */ - getDecimals: () => number + getDecimals: () => Promise /** * @returns Total supply of the token */ - getTotalSupply: () => number + getTotalSupply: () => Promise /** * Gives permission to the spender to spend owner's tokens @@ -84,14 +88,14 @@ export interface TokenInterface extends AssetInterface, ContractInterface { * @param spender Address of the spender that will use the tokens of owner * @param amount Amount of the tokens that will be used */ - approve: (owner: string, spender: string, amount: number) => TransactionSignerInterface + approve: (owner: string, spender: string, amount: number) => Promise /** * @param owner Address of owner of the tokens that is being used * @param spender Address of the spender that is using the tokens of owner * @returns Amount of the tokens that is being used by spender */ - allowance: (owner: string, spender: string) => number + allowance: (owner: string, spender: string) => Promise } export interface NftInterface extends Omit, ContractInterface { @@ -99,13 +103,13 @@ export interface NftInterface extends Omit, Contract * @param nftId ID of the NFT * @returns Wallet address of owner of the NFT */ - getOwner: (nftId: number) => string + getOwner: (nftId: number) => Promise /** * @param nftId ID of the NFT * @returns URL of the metadata */ - getTokenURI: (nftId: number) => string | URL + getTokenURI: (nftId: number) => Promise /** * Transfers an NFT @@ -114,5 +118,9 @@ export interface NftInterface extends Omit, Contract * @param nftId ID of the NFT that will be transferred * @override transfer() in AssetInterface */ - transfer: (sender: string, receiver: string, nftId: number) => TransactionSignerInterface + transfer: ( + sender: string, + receiver: string, + nftId: number + ) => Promise } diff --git a/packages/types/src/services/TransactionSignerInterface.ts b/packages/types/src/services/TransactionSignerInterface.ts index 8f01f34..cac39d9 100644 --- a/packages/types/src/services/TransactionSignerInterface.ts +++ b/packages/types/src/services/TransactionSignerInterface.ts @@ -18,7 +18,7 @@ export interface TransactionSignerInterface { /** * @param privateKey - Private key of the wallet to sign the transaction */ - sign: (privateKey: string) => TransactionSignerInterface + sign: (privateKey: string) => Promise /** * @returns Send the transaction to the blockchain network, returns a promise of the transaction From dfaa4c3963106318408aadcccb4033df33df7076 Mon Sep 17 00:00:00 2001 From: Halil Beycan <50718965+BeycanDeveloper@users.noreply.github.com> Date: Mon, 18 Mar 2024 23:08:58 +0800 Subject: [PATCH 002/114] version upgrade --- packages/types/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/types/package.json b/packages/types/package.json index 5f611a9..81dca03 100644 --- a/packages/types/package.json +++ b/packages/types/package.json @@ -1,6 +1,6 @@ { "name": "@multiplechain/types", - "version": "0.1.13", + "version": "0.1.14", "type": "module", "main": "./src/index.ts", "types": "./src/index.ts", From 2b192873a8c1943c6a472d9850a0295ef9f3ea61 Mon Sep 17 00:00:00 2001 From: Halil Beycan <50718965+BeycanDeveloper@users.noreply.github.com> Date: Mon, 18 Mar 2024 23:13:25 +0800 Subject: [PATCH 003/114] Coin asset is completed --- packages/networks/evm-chains/package.json | 2 +- packages/networks/evm-chains/pnpm-lock.yaml | 8 +-- .../networks/evm-chains/src/assets/Coin.ts | 53 +++++++++++++-- .../evm-chains/src/models/Transaction.ts | 4 +- .../evm-chains/src/services/Ethers.ts | 54 +++++++++------ .../evm-chains/src/services/Provider.ts | 22 +++--- .../src/services/TransactionSigner.ts | 28 ++++++-- .../networks/evm-chains/tests/assets.spec.ts | 67 +++++++++++++++++-- packages/networks/evm-chains/tests/setup.ts | 1 + tsconfig.json | 3 +- 10 files changed, 186 insertions(+), 56 deletions(-) diff --git a/packages/networks/evm-chains/package.json b/packages/networks/evm-chains/package.json index d300bc7..e8a9dcf 100644 --- a/packages/networks/evm-chains/package.json +++ b/packages/networks/evm-chains/package.json @@ -38,7 +38,7 @@ "url": "https://github.com/MultipleChain/js/issues" }, "dependencies": { - "@multiplechain/types": "^0.1.13", + "@multiplechain/types": "^0.1.14", "@multiplechain/utils": "^0.1.7" } } \ No newline at end of file diff --git a/packages/networks/evm-chains/pnpm-lock.yaml b/packages/networks/evm-chains/pnpm-lock.yaml index 16249c9..06e65df 100644 --- a/packages/networks/evm-chains/pnpm-lock.yaml +++ b/packages/networks/evm-chains/pnpm-lock.yaml @@ -6,16 +6,16 @@ settings: dependencies: '@multiplechain/types': - specifier: ^0.1.13 - version: 0.1.13 + specifier: ^0.1.14 + version: 0.1.14 '@multiplechain/utils': specifier: ^0.1.7 version: 0.1.7 packages: - /@multiplechain/types@0.1.13: - resolution: {integrity: sha512-sM+J8YKUPDh35aOtUv4dytv8Lq+ezVXSktNew7ngIpEgW2pubqsTLmFmAmI4H58DHd5XowQvK6cbApne6q4/Ug==} + /@multiplechain/types@0.1.14: + resolution: {integrity: sha512-l1OYiodb7zqFkoEb+j60aGFRFkmmQjS/VKAbbXfB+kQo9GgGtK1Y7nGyfQEpcxz7XZh3GSr5k0tMOXFZb6LuQw==} dev: false /@multiplechain/utils@0.1.7: diff --git a/packages/networks/evm-chains/src/assets/Coin.ts b/packages/networks/evm-chains/src/assets/Coin.ts index ce9952e..edac33f 100644 --- a/packages/networks/evm-chains/src/assets/Coin.ts +++ b/packages/networks/evm-chains/src/assets/Coin.ts @@ -1,34 +1,40 @@ import { TransactionSigner } from '../services/TransactionSigner.ts' import type { CoinInterface, TransactionSignerInterface } from '@multiplechain/types' +import { Provider } from '../services/Provider.ts' +import { hexToNumber, numberToHex } from '@multiplechain/utils' +import type { TransactionData } from '../services/TransactionSigner.ts' + +const { network, ethers } = Provider.instance export class Coin implements CoinInterface { /** * @returns Coin name */ getName(): string { - return 'example' + return network.nativeCurrency.name ?? network.nativeCurrency.symbol } /** * @returns Coin symbol */ getSymbol(): string { - return 'example' + return network.nativeCurrency.symbol } /** * @returns Decimal value of the coin */ getDecimals(): number { - return 18 + return network.nativeCurrency.decimals } /** * @param owner Wallet address * @returns Wallet balance as currency of TOKEN or COIN assets */ - getBalance(owner: string): number { - return 0 + async getBalance(owner: string): Promise { + const balance = await ethers.getBalance(owner) + return hexToNumber(balance.toString(), this.getDecimals()) } /** @@ -36,7 +42,40 @@ export class Coin implements CoinInterface { * @param receiver Receiver wallet address * @param amount Amount of assets that will be transferred */ - transfer(sender: string, receiver: string, amount: number): TransactionSignerInterface { - return new TransactionSigner('example') + async transfer( + sender: string, + receiver: string, + amount: number + ): Promise { + if (amount < 0) { + throw new Error('Invalid amount') + } + + if (amount > (await this.getBalance(sender))) { + throw new Error('Insufficient balance') + } + + const hexAmount = numberToHex(amount, this.getDecimals()) + + const txData: TransactionData = { + data: '0x', + to: receiver, + from: sender, + chainId: network.id, + value: hexAmount + } + + const [gasPrice, nonce, gas] = await Promise.all([ + ethers.getGasPrice(), + ethers.getNonce(sender), + ethers.getEstimateGas(txData) + ]) + + txData.gas = gas + txData.nonce = nonce + txData.gasPrice = gasPrice + txData.gasLimit = 21000 + + return new TransactionSigner(txData) } } diff --git a/packages/networks/evm-chains/src/models/Transaction.ts b/packages/networks/evm-chains/src/models/Transaction.ts index c45b61f..4c470b7 100644 --- a/packages/networks/evm-chains/src/models/Transaction.ts +++ b/packages/networks/evm-chains/src/models/Transaction.ts @@ -30,9 +30,9 @@ export class Transaction implements TransactionInterface { } catch (error) { const e = error as Error if (String(e.message).includes('timeout')) { - throw new Error('rpc-timeout') + throw new Error('RPC Timeout') } - throw new Error('data-request-failed') + throw new Error('Transaction not found') } } diff --git a/packages/networks/evm-chains/src/services/Ethers.ts b/packages/networks/evm-chains/src/services/Ethers.ts index 2eb2c49..50b1ced 100644 --- a/packages/networks/evm-chains/src/services/Ethers.ts +++ b/packages/networks/evm-chains/src/services/Ethers.ts @@ -6,17 +6,12 @@ import type { TransactionResponse } from 'ethers' -import { Contract, ContractFactory, JsonRpcProvider, WebSocketProvider } from 'ethers' +import { Wallet, Contract, ContractFactory, JsonRpcProvider, WebSocketProvider } from 'ethers' import { toHex } from '@multiplechain/utils' import type { EvmNetworkConfigInterface } from './Provider.ts' - -declare module 'ethers' { - interface JsonRpcProvider { - getGasPrice: () => Promise - } -} +import type { TransactionData } from '../services/TransactionSigner.ts' export class Ethers { network: EvmNetworkConfigInterface @@ -47,32 +42,45 @@ export class Ethers { /** * @param {String} address * @param {object[]} abi - * @param {JsonRpcSigner} provider - * @returns {Object} + * @param {JsonRpcSigner} signer + * @returns {Promise} + */ + public async contract( + address: string, + abi: object[], + signer?: JsonRpcSigner + ): Promise { + return new Contract(address, abi, signer ?? (await this.jsonRpc.getSigner())) + } + + /** + * @param privateKey private key of the wallet + * @param provider provider of the blockchain network + * @returns {Wallet} */ - public contract(address: string, abi: object[], provider?: JsonRpcSigner): Contract { - return new Contract(address, abi, provider) + public wallet(privateKey: string, provider?: JsonRpcProvider): Wallet { + return new Wallet(privateKey, provider ?? this.jsonRpc) } /** * @param {object[]} abi * @param {String} bytecode - * @param {JsonRpcSigner} provider - * @returns {Object} + * @param {JsonRpcSigner} signer + * @returns {Promise} */ - public contractFactory( + public async contractFactory( abi: object[], bytecode: string, - provider?: JsonRpcSigner - ): ContractFactory { - return new ContractFactory(abi, bytecode, provider) + signer?: JsonRpcSigner + ): Promise { + return new ContractFactory(abi, bytecode, signer ?? (await this.jsonRpc.getSigner())) } /** * @param {Object} data * @returns {Promise} */ - public async getEstimateGas(data: object): Promise { + public async getEstimateGas(data: TransactionData): Promise { return toHex((await this.jsonRpcProvider.estimateGas(data)).toString()) } @@ -80,7 +88,15 @@ export class Ethers { * @returns {Promise} */ public async getGasPrice(): Promise { - return toHex((await this.jsonRpcProvider.getGasPrice()).toString()) + return (await this.jsonRpc.send('eth_gasPrice', [])).toString() as string + } + + /** + * @param {String} address + * @returns {Promise} + */ + public async getNonce(address: string): Promise { + return await this.jsonRpcProvider.getTransactionCount(address) } /** diff --git a/packages/networks/evm-chains/src/services/Provider.ts b/packages/networks/evm-chains/src/services/Provider.ts index 9c9ef70..c38e38d 100644 --- a/packages/networks/evm-chains/src/services/Provider.ts +++ b/packages/networks/evm-chains/src/services/Provider.ts @@ -15,21 +15,21 @@ export interface EvmNetworkConfigInterface extends NetworkConfigInterface { } } -export class Provider implements Omit { +export class Provider implements Omit { /** * Network configuration of the provider */ - private network: EvmNetworkConfigInterface + public network: EvmNetworkConfigInterface /** * Ethers service */ - private _ethers: Ethers + public ethers: Ethers /** * Static instance of the provider */ - private static _instance: Provider + public static _instance: Provider /** * @param network - Network configuration of the provider @@ -37,14 +37,7 @@ export class Provider implements Omit { constructor(network: EvmNetworkConfigInterface) { this.network = network Provider._instance = this - this._ethers = new Ethers(network) - } - - /** - * @returns Ethers service instance - */ - get ethers(): Ethers { - return this._ethers + this.ethers = new Ethers(network) } /** @@ -63,6 +56,9 @@ export class Provider implements Omit { * @param network - Network configuration of the provider */ static initialize(network: EvmNetworkConfigInterface): void { + if (Provider._instance !== undefined) { + throw new Error('Provider is already initialized') + } Provider._instance = new Provider(network) } @@ -73,7 +69,7 @@ export class Provider implements Omit { update(network: EvmNetworkConfigInterface): void { this.network = network Provider._instance = this - this._ethers = new Ethers(network) + this.ethers = new Ethers(network) } /** diff --git a/packages/networks/evm-chains/src/services/TransactionSigner.ts b/packages/networks/evm-chains/src/services/TransactionSigner.ts index b791561..db23e8b 100644 --- a/packages/networks/evm-chains/src/services/TransactionSigner.ts +++ b/packages/networks/evm-chains/src/services/TransactionSigner.ts @@ -1,20 +1,34 @@ import type { TransactionSignerInterface, TransactionInterface } from '@multiplechain/types' +import { Provider } from '../services/Provider.ts' +import type { TransactionRequest, Wallet } from 'ethers' +import { Transaction } from '../models/Transaction.ts' + +export interface TransactionData extends TransactionRequest { + gas?: string +} + +const { ethers } = Provider.instance export class TransactionSigner implements TransactionSignerInterface { /** * Transaction data from the blockchain network */ - rawData: any + rawData: TransactionData /** * Signed transaction data */ - signedData?: any + signedData: string + + /** + * Wallet instance from ethers with the private key + */ + wallet: Wallet /** * @param rawData - Transaction data */ - constructor(rawData: any) { + constructor(rawData: TransactionData) { this.rawData = rawData } @@ -22,7 +36,9 @@ export class TransactionSigner implements TransactionSignerInterface { * Sign the transaction * @param privateKey - Transaction data */ - sign(privateKey: string): this { + public async sign(privateKey: string): Promise { + this.wallet = ethers.wallet(privateKey) + this.signedData = await this.wallet.signTransaction(this.rawData) return this } @@ -31,7 +47,9 @@ export class TransactionSigner implements TransactionSignerInterface { * @returns Promise of the transaction */ async send(): Promise { - return await Promise.resolve(this.signedData) + return new Transaction( + (await ethers.jsonRpc.send('eth_sendRawTransaction', [this.signedData])).hash as string + ) } /** diff --git a/packages/networks/evm-chains/tests/assets.spec.ts b/packages/networks/evm-chains/tests/assets.spec.ts index b19c282..687516f 100644 --- a/packages/networks/evm-chains/tests/assets.spec.ts +++ b/packages/networks/evm-chains/tests/assets.spec.ts @@ -1,7 +1,66 @@ -import { describe, it, expect } from 'vitest' +import { describe, it, expect, assert } from 'vitest' -describe('Tests for assets', () => { - it('should load assets', async () => { - expect(1).toBe(1) +import { Coin } from '../src/assets/Coin.ts' +import { TransactionSigner } from '../src/services/TransactionSigner.ts' +import { Transaction } from '../src/models/Transaction.ts' + +const balanceTestAddress = '0x760A4d3D03928D1e8541A7644B34370c1b79aa9F' +const tokenTestAddress = '0x4294cb0dD25dC9140B5127f247cBd47Eeb673431' +const coinBalanceTestAmount = 0.01 +const tokenBalanceTestAmount = 1000 + +const walletPrivateKey = '14bd9af4e87981b37b7b2e8a0d1d249b7fcdb7a3bc579c4c31488842d372c0e9' +const senderTestAddress = '0x110600bF0399174520a159ed425f0D272Ff8b459' +const receiverTestAddress = '0xbBa4d06D1cEf94b35aDeCfDa893523907fdD36DE' +const transferTestAmount = 0.0001 + +describe('Coin', () => { + const coin = new Coin() + it('Name and symbol', () => { + expect(coin.getName()).toBe('Ethereum') + expect(coin.getSymbol()).toBe('ETH') + }) + + it('Decimals', () => { + expect(coin.getDecimals()).toBe(18) + }) + + it('Balance', async () => { + const balance = await coin.getBalance(balanceTestAddress) + expect(balance).toBe(coinBalanceTestAmount) + }) + + it('Transfer', async () => { + const signer = await coin.transfer( + senderTestAddress, + receiverTestAddress, + transferTestAmount + ) + + expect(signer).toBeInstanceOf(TransactionSigner) + + const rawData = signer.getRawData() + + assert.isObject(rawData) + + await signer.sign(walletPrivateKey) + + assert.isString(signer.getSignedData()) + + // const beforeBalance = await coin.getBalance(receiverTestAddress) + + const transaction = await signer.send() + + expect(transaction).toBeInstanceOf(Transaction) + + // TODO: Complete after coin transaction verify method is implemented + // const afterBalance = await coin.getBalance(receiverTestAddress) + // expect(afterBalance).toBe(beforeBalance + transferTestAmount) }) }) + +// describe('Contract', () => {}) + +// describe('Token', () => {}) + +// describe('Nft', () => {}) diff --git a/packages/networks/evm-chains/tests/setup.ts b/packages/networks/evm-chains/tests/setup.ts index 59e6837..3aa18e1 100644 --- a/packages/networks/evm-chains/tests/setup.ts +++ b/packages/networks/evm-chains/tests/setup.ts @@ -10,6 +10,7 @@ export const provider = new Provider({ explorerUrl: 'https://sepolia.etherscan.io/', nativeCurrency: { symbol: 'ETH', + name: 'Ethereum', decimals: 18 } }) diff --git a/tsconfig.json b/tsconfig.json index c37f876..baadf30 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -18,7 +18,8 @@ "strict": true, "noUnusedLocals": true, "noUnusedParameters": true, - "noFallthroughCasesInSwitch": true + "noFallthroughCasesInSwitch": true, + "strictPropertyInitialization": false }, "include": ["packages/**/*.ts", ".eslintrc.json", "vite.config.ts", "vitest.config.ts", "vite-env.d.ts"], "exclude": ["node_modules", "dist", "packages/**/*.d.ts"] From 6fb0c2aa1d8b1af6191e38a2f152346448b91d97 Mon Sep 17 00:00:00 2001 From: Halil Beycan <50718965+BeycanDeveloper@users.noreply.github.com> Date: Sun, 24 Mar 2024 13:37:59 +0800 Subject: [PATCH 004/114] updated --- packages/networks/boilerplate/pnpm-lock.yaml | 276 ++++++++++++++++++ .../networks/boilerplate/src/assets/Asset.ts | 36 --- .../networks/boilerplate/src/assets/Coin.ts | 10 +- .../boilerplate/src/assets/Contract.ts | 4 +- .../networks/boilerplate/src/assets/NFT.ts | 25 +- .../networks/boilerplate/src/assets/Token.ts | 31 +- .../src/models/AssetTransaction.ts | 32 -- .../boilerplate/src/models/CoinTransaction.ts | 8 +- .../src/models/ContractTransaction.ts | 2 +- .../boilerplate/src/models/NftTransaction.ts | 12 +- .../src/models/TokenTransaction.ts | 14 +- .../boilerplate/src/models/Transaction.ts | 14 +- .../src/services/TransactionSigner.ts | 4 +- 13 files changed, 339 insertions(+), 129 deletions(-) create mode 100644 packages/networks/boilerplate/pnpm-lock.yaml delete mode 100644 packages/networks/boilerplate/src/assets/Asset.ts delete mode 100644 packages/networks/boilerplate/src/models/AssetTransaction.ts diff --git a/packages/networks/boilerplate/pnpm-lock.yaml b/packages/networks/boilerplate/pnpm-lock.yaml new file mode 100644 index 0000000..e032632 --- /dev/null +++ b/packages/networks/boilerplate/pnpm-lock.yaml @@ -0,0 +1,276 @@ +lockfileVersion: '6.0' + +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false + +dependencies: + '@multiplechain/types': + specifier: ^0.1.13 + version: 0.1.15 + '@multiplechain/utils': + specifier: ^0.1.7 + version: 0.1.7 + +packages: + + /@multiplechain/types@0.1.15: + resolution: {integrity: sha512-BwXCEUHob1yxjca9AklG546EZeE5DNPRmXdKr1i4bFeWSb4jXDVKWw+KwJcusDTiFUufja8XqsM43I7tFpDCIg==} + dev: false + + /@multiplechain/utils@0.1.7: + resolution: {integrity: sha512-I29JEiL+OTs6I6Lb4dTSsshcODttgO8oeCIP0xvJnkebIHz8ODyNG6rnQtUV/cOHhf4S12ZBkLN4FNJFuy/Mmw==} + dependencies: + bignumber.js: 9.1.2 + web3-utils: 4.2.1 + dev: false + + /@noble/curves@1.3.0: + resolution: {integrity: sha512-t01iSXPuN+Eqzb4eBX0S5oubSqXbK/xXa1Ne18Hj8f9pStxztHCE2gfboSp/dZRLSqfuLpRK2nDXDK+W9puocA==} + dependencies: + '@noble/hashes': 1.3.3 + dev: false + + /@noble/hashes@1.3.3: + resolution: {integrity: sha512-V7/fPHgl+jsVPXqqeOzT8egNj2iBIVt+ECeMMG8TdcnTikP3oaBtUVqpT/gYCR68aEBJSF+XbYUxStjbFMqIIA==} + engines: {node: '>= 16'} + dev: false + + /@scure/base@1.1.6: + resolution: {integrity: sha512-ok9AWwhcgYuGG3Zfhyqg+zwl+Wn5uE+dwC0NV/2qQkx4dABbb/bx96vWu8NSj+BNjjSjno+JRYRjle1jV08k3g==} + dev: false + + /@scure/bip32@1.3.3: + resolution: {integrity: sha512-LJaN3HwRbfQK0X1xFSi0Q9amqOgzQnnDngIt+ZlsBC3Bm7/nE7K0kwshZHyaru79yIVRv/e1mQAjZyuZG6jOFQ==} + dependencies: + '@noble/curves': 1.3.0 + '@noble/hashes': 1.3.3 + '@scure/base': 1.1.6 + dev: false + + /@scure/bip39@1.2.2: + resolution: {integrity: sha512-HYf9TUXG80beW+hGAt3TRM8wU6pQoYur9iNypTROm42dorCGmLnFe3eWjz3gOq6G62H2WRh0FCzAR1PI+29zIA==} + dependencies: + '@noble/hashes': 1.3.3 + '@scure/base': 1.1.6 + dev: false + + /available-typed-arrays@1.0.7: + resolution: {integrity: sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==} + engines: {node: '>= 0.4'} + dependencies: + possible-typed-array-names: 1.0.0 + dev: false + + /bignumber.js@9.1.2: + resolution: {integrity: sha512-2/mKyZH9K85bzOEfhXDBFZTGd1CTs+5IHpeFQo9luiBG7hghdC851Pj2WAhb6E3R6b9tZj/XKhbg4fum+Kepug==} + dev: false + + /call-bind@1.0.7: + resolution: {integrity: sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==} + engines: {node: '>= 0.4'} + dependencies: + es-define-property: 1.0.0 + es-errors: 1.3.0 + function-bind: 1.1.2 + get-intrinsic: 1.2.4 + set-function-length: 1.2.2 + dev: false + + /define-data-property@1.1.4: + resolution: {integrity: sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==} + engines: {node: '>= 0.4'} + dependencies: + es-define-property: 1.0.0 + es-errors: 1.3.0 + gopd: 1.0.1 + dev: false + + /es-define-property@1.0.0: + resolution: {integrity: sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==} + engines: {node: '>= 0.4'} + dependencies: + get-intrinsic: 1.2.4 + dev: false + + /es-errors@1.3.0: + resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==} + engines: {node: '>= 0.4'} + dev: false + + /ethereum-cryptography@2.1.3: + resolution: {integrity: sha512-BlwbIL7/P45W8FGW2r7LGuvoEZ+7PWsniMvQ4p5s2xCyw9tmaDlpfsN9HjAucbF+t/qpVHwZUisgfK24TCW8aA==} + dependencies: + '@noble/curves': 1.3.0 + '@noble/hashes': 1.3.3 + '@scure/bip32': 1.3.3 + '@scure/bip39': 1.2.2 + dev: false + + /eventemitter3@5.0.1: + resolution: {integrity: sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==} + dev: false + + /for-each@0.3.3: + resolution: {integrity: sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==} + dependencies: + is-callable: 1.2.7 + dev: false + + /function-bind@1.1.2: + resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} + dev: false + + /get-intrinsic@1.2.4: + resolution: {integrity: sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==} + engines: {node: '>= 0.4'} + dependencies: + es-errors: 1.3.0 + function-bind: 1.1.2 + has-proto: 1.0.3 + has-symbols: 1.0.3 + hasown: 2.0.2 + dev: false + + /gopd@1.0.1: + resolution: {integrity: sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==} + dependencies: + get-intrinsic: 1.2.4 + dev: false + + /has-property-descriptors@1.0.2: + resolution: {integrity: sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==} + dependencies: + es-define-property: 1.0.0 + dev: false + + /has-proto@1.0.3: + resolution: {integrity: sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==} + engines: {node: '>= 0.4'} + dev: false + + /has-symbols@1.0.3: + resolution: {integrity: sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==} + engines: {node: '>= 0.4'} + dev: false + + /has-tostringtag@1.0.2: + resolution: {integrity: sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==} + engines: {node: '>= 0.4'} + dependencies: + has-symbols: 1.0.3 + dev: false + + /hasown@2.0.2: + resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} + engines: {node: '>= 0.4'} + dependencies: + function-bind: 1.1.2 + dev: false + + /inherits@2.0.4: + resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} + dev: false + + /is-arguments@1.1.1: + resolution: {integrity: sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.7 + has-tostringtag: 1.0.2 + dev: false + + /is-callable@1.2.7: + resolution: {integrity: sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==} + engines: {node: '>= 0.4'} + dev: false + + /is-generator-function@1.0.10: + resolution: {integrity: sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==} + engines: {node: '>= 0.4'} + dependencies: + has-tostringtag: 1.0.2 + dev: false + + /is-typed-array@1.1.13: + resolution: {integrity: sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw==} + engines: {node: '>= 0.4'} + dependencies: + which-typed-array: 1.1.15 + dev: false + + /possible-typed-array-names@1.0.0: + resolution: {integrity: sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==} + engines: {node: '>= 0.4'} + dev: false + + /set-function-length@1.2.2: + resolution: {integrity: sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==} + engines: {node: '>= 0.4'} + dependencies: + define-data-property: 1.1.4 + es-errors: 1.3.0 + function-bind: 1.1.2 + get-intrinsic: 1.2.4 + gopd: 1.0.1 + has-property-descriptors: 1.0.2 + dev: false + + /util@0.12.5: + resolution: {integrity: sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA==} + dependencies: + inherits: 2.0.4 + is-arguments: 1.1.1 + is-generator-function: 1.0.10 + is-typed-array: 1.1.13 + which-typed-array: 1.1.15 + dev: false + + /web3-errors@1.1.4: + resolution: {integrity: sha512-WahtszSqILez+83AxGecVroyZsMuuRT+KmQp4Si5P4Rnqbczno1k748PCrZTS1J4UCPmXMG2/Vt+0Bz2zwXkwQ==} + engines: {node: '>=14', npm: '>=6.12.0'} + dependencies: + web3-types: 1.5.0 + dev: false + + /web3-types@1.5.0: + resolution: {integrity: sha512-geWuMIeegQ8AedKAO6wO4G4j1gyQ1F/AyKLMw2vud4bsfZayyzWJgCMDZtjYMm5uo2a7i8j1W3/4QFmzlSy5cw==} + engines: {node: '>=14', npm: '>=6.12.0'} + dev: false + + /web3-utils@4.2.1: + resolution: {integrity: sha512-Fk29BlEqD9Q9Cnw4pBkKw7czcXiRpsSco/BzEUl4ye0ZTSHANQFfjsfQmNm4t7uY11u6Ah+8F3tNjBeU4CA80A==} + engines: {node: '>=14', npm: '>=6.12.0'} + dependencies: + ethereum-cryptography: 2.1.3 + eventemitter3: 5.0.1 + web3-errors: 1.1.4 + web3-types: 1.5.0 + web3-validator: 2.0.4 + dev: false + + /web3-validator@2.0.4: + resolution: {integrity: sha512-qRxVePwdW+SByOmTpDZFWHIUAa7PswvxNszrOua6BoGqAhERo5oJZBN+EbWtK/+O+ApNxt5FR3nCPmiZldiOQA==} + engines: {node: '>=14', npm: '>=6.12.0'} + dependencies: + ethereum-cryptography: 2.1.3 + util: 0.12.5 + web3-errors: 1.1.4 + web3-types: 1.5.0 + zod: 3.22.4 + dev: false + + /which-typed-array@1.1.15: + resolution: {integrity: sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA==} + engines: {node: '>= 0.4'} + dependencies: + available-typed-arrays: 1.0.7 + call-bind: 1.0.7 + for-each: 0.3.3 + gopd: 1.0.1 + has-tostringtag: 1.0.2 + dev: false + + /zod@3.22.4: + resolution: {integrity: sha512-iC+8Io04lddc+mVqQ9AZ7OQ2MrUKGN+oIQyq1vemgt46jwCwLfhq7/pwnBnNXXXZb8VTVLKwp9EDkx+ryxIWmg==} + dev: false diff --git a/packages/networks/boilerplate/src/assets/Asset.ts b/packages/networks/boilerplate/src/assets/Asset.ts deleted file mode 100644 index 3a95dcd..0000000 --- a/packages/networks/boilerplate/src/assets/Asset.ts +++ /dev/null @@ -1,36 +0,0 @@ -import { TransactionSigner } from '../services/TransactionSigner.ts' -import type { AssetInterface, TransactionSignerInterface } from '@multiplechain/types' - -export class Asset implements AssetInterface { - /** - * @returns Asset name - */ - getName(): string { - return 'example' - } - - /** - * @returns Asset symbol - */ - getSymbol(): string { - return 'example' - } - - /** - * @param owner Wallet address - * @returns Wallet balance as currency of TOKEN or COIN assets - */ - getBalance(owner: string): number { - return 0 - } - - /** - * transfer() method is the main method for processing transfers for fungible assets (TOKEN, COIN) - * @param sender Sender wallet address - * @param receiver Receiver wallet address - * @param amount Amount of assets that will be transferred - */ - transfer(sender: string, receiver: string, amount: number): TransactionSignerInterface { - return new TransactionSigner('example') - } -} diff --git a/packages/networks/boilerplate/src/assets/Coin.ts b/packages/networks/boilerplate/src/assets/Coin.ts index ce9952e..11dae68 100644 --- a/packages/networks/boilerplate/src/assets/Coin.ts +++ b/packages/networks/boilerplate/src/assets/Coin.ts @@ -19,7 +19,7 @@ export class Coin implements CoinInterface { /** * @returns Decimal value of the coin */ - getDecimals(): number { + async getDecimals(): Promise { return 18 } @@ -27,7 +27,7 @@ export class Coin implements CoinInterface { * @param owner Wallet address * @returns Wallet balance as currency of TOKEN or COIN assets */ - getBalance(owner: string): number { + async getBalance(owner: string): Promise { return 0 } @@ -36,7 +36,11 @@ export class Coin implements CoinInterface { * @param receiver Receiver wallet address * @param amount Amount of assets that will be transferred */ - transfer(sender: string, receiver: string, amount: number): TransactionSignerInterface { + async transfer( + sender: string, + receiver: string, + amount: number + ): Promise { return new TransactionSigner('example') } } diff --git a/packages/networks/boilerplate/src/assets/Contract.ts b/packages/networks/boilerplate/src/assets/Contract.ts index a16e5dc..e52c40c 100644 --- a/packages/networks/boilerplate/src/assets/Contract.ts +++ b/packages/networks/boilerplate/src/assets/Contract.ts @@ -22,7 +22,7 @@ export class Contract implements ContractInterface { * @param args Method parameters * @returns Method result */ - callMethod(method: string, ...args: any[]): any { + async callMethod(method: string, ...args: any[]): Promise { return {} } @@ -31,7 +31,7 @@ export class Contract implements ContractInterface { * @param args Method parameters * @returns Method data */ - getMethodData(method: string, ...args: any[]): any { + async getMethodData(method: string, ...args: any[]): Promise { return {} } } diff --git a/packages/networks/boilerplate/src/assets/NFT.ts b/packages/networks/boilerplate/src/assets/NFT.ts index 155c666..500989a 100644 --- a/packages/networks/boilerplate/src/assets/NFT.ts +++ b/packages/networks/boilerplate/src/assets/NFT.ts @@ -6,14 +6,14 @@ export class NFT extends Contract implements NftInterface { /** * @returns Contract name */ - getName(): string { + async getName(): Promise { return 'example' } /** * @returns Contract symbol */ - getSymbol(): string { + async getSymbol(): Promise { return 'example' } @@ -21,21 +21,14 @@ export class NFT extends Contract implements NftInterface { * @param owner Wallet address * @returns Wallet balance as currency of TOKEN or COIN assets */ - getBalance(owner: string): number { + async getBalance(owner: string): Promise { return 0 } - /** - * @returns Contract address - */ - getAddress(): string { - return 'example' - } - /** * @returns NFT ID */ - getNftId(): number { + async getNftId(): Promise { return 0 } @@ -45,7 +38,11 @@ export class NFT extends Contract implements NftInterface { * @param nftId NFT ID * @returns Transaction signer */ - transfer(sender: string, receiver: string, nftId: number): TransactionSignerInterface { + async transfer( + sender: string, + receiver: string, + nftId: number + ): Promise { return new TransactionSigner('example') } @@ -53,7 +50,7 @@ export class NFT extends Contract implements NftInterface { * @param nftId NFT ID * @returns NFT owner wallet address */ - getOwner(nftId: number): string { + async getOwner(nftId: number): Promise { return 'example' } @@ -61,7 +58,7 @@ export class NFT extends Contract implements NftInterface { * @param nftId NFT ID * @returns NFT URI */ - getTokenURI(nftId: number): string { + async getTokenURI(nftId: number): Promise { return 'example' } } diff --git a/packages/networks/boilerplate/src/assets/Token.ts b/packages/networks/boilerplate/src/assets/Token.ts index 5853f5f..8b4acea 100644 --- a/packages/networks/boilerplate/src/assets/Token.ts +++ b/packages/networks/boilerplate/src/assets/Token.ts @@ -6,28 +6,21 @@ export class Token extends Contract implements TokenInterface { /** * @returns Token name */ - getName(): string { + async getName(): Promise { return 'example' } /** * @returns Token symbol */ - getSymbol(): string { - return 'example' - } - - /** - * @returns Contract address - */ - getAddress(): string { + async getSymbol(): Promise { return 'example' } /** * @returns Decimal value of the coin */ - getDecimals(): number { + async getDecimals(): Promise { return 18 } @@ -35,14 +28,14 @@ export class Token extends Contract implements TokenInterface { * @param owner Wallet address * @returns Wallet balance as currency of TOKEN or COIN assets */ - getBalance(owner: string): number { + async getBalance(owner: string): Promise { return 0 } /** * @returns Total supply of the token */ - getTotalSupply(): number { + async getTotalSupply(): Promise { return 0 } @@ -52,7 +45,11 @@ export class Token extends Contract implements TokenInterface { * @param receiver Receiver wallet address * @param amount Amount of assets that will be transferred */ - transfer(sender: string, receiver: string, amount: number): TransactionSignerInterface { + async transfer( + sender: string, + receiver: string, + amount: number + ): Promise { return new TransactionSigner('example') } @@ -62,7 +59,11 @@ export class Token extends Contract implements TokenInterface { * @param spender Address of the spender that will use the tokens of owner * @param amount Amount of the tokens that will be used */ - approve(owner: string, spender: string, amount: number): TransactionSignerInterface { + async approve( + owner: string, + spender: string, + amount: number + ): Promise { return new TransactionSigner('example') } @@ -71,7 +72,7 @@ export class Token extends Contract implements TokenInterface { * @param spender Address of the spender that is using the tokens of owner * @returns Amount of the tokens that is being used by spender */ - allowance(owner: string, spender: string): number { + async allowance(owner: string, spender: string): Promise { return 0 } } diff --git a/packages/networks/boilerplate/src/models/AssetTransaction.ts b/packages/networks/boilerplate/src/models/AssetTransaction.ts deleted file mode 100644 index e4cb42d..0000000 --- a/packages/networks/boilerplate/src/models/AssetTransaction.ts +++ /dev/null @@ -1,32 +0,0 @@ -import { Transaction } from './Transaction.ts' -import { TransactionStatusEnum } from '@multiplechain/types' -import type { AssetTransactionInterface, AssetDirectionEnum } from '@multiplechain/types' - -export class AssetTransaction extends Transaction implements AssetTransactionInterface { - /** - * @returns Receiver wallet address of the transaction (asset) - */ - getReceiver(): string { - return 'example' - } - - /** - * @returns Transfer amount of the transaction (coin) - */ - getAmount(): number { - return 0 - } - - /** - * @param direction - Direction of the transaction (asset) - * @param address - Wallet address of the receiver or sender of the transaction, dependant on direction - * @param amount Amount of assets that will be transferred - */ - verifyTransfer( - direction: AssetDirectionEnum, - address: string, - amount: number - ): TransactionStatusEnum { - return TransactionStatusEnum.CONFIRMED - } -} diff --git a/packages/networks/boilerplate/src/models/CoinTransaction.ts b/packages/networks/boilerplate/src/models/CoinTransaction.ts index e8e2fa8..ec93b84 100644 --- a/packages/networks/boilerplate/src/models/CoinTransaction.ts +++ b/packages/networks/boilerplate/src/models/CoinTransaction.ts @@ -6,14 +6,14 @@ export class CoinTransaction extends Transaction implements CoinTransactionInter /** * @returns Wallet address of the sender of transaction */ - getReceiver(): string { + async getReceiver(): Promise { return 'example' } /** * @returns Transfer amount of the transaction (coin) */ - getAmount(): number { + async getAmount(): Promise { return 0 } @@ -22,11 +22,11 @@ export class CoinTransaction extends Transaction implements CoinTransactionInter * @param address - Wallet address of the receiver or sender of the transaction, dependant on direction * @param amount Amount of assets that will be transferred */ - verifyTransfer( + async verifyTransfer( direction: AssetDirectionEnum, address: string, amount: number - ): TransactionStatusEnum { + ): Promise { return TransactionStatusEnum.PENDING } } diff --git a/packages/networks/boilerplate/src/models/ContractTransaction.ts b/packages/networks/boilerplate/src/models/ContractTransaction.ts index cb6f829..c48396b 100644 --- a/packages/networks/boilerplate/src/models/ContractTransaction.ts +++ b/packages/networks/boilerplate/src/models/ContractTransaction.ts @@ -2,7 +2,7 @@ import { Transaction } from './Transaction.ts' import type { ContractTransactionInterface } from '@multiplechain/types' export class ContractTransaction extends Transaction implements ContractTransactionInterface { - getAddress(): string { + async getAddress(): Promise { return 'example' } } diff --git a/packages/networks/boilerplate/src/models/NftTransaction.ts b/packages/networks/boilerplate/src/models/NftTransaction.ts index 92dea08..8dd9d6b 100644 --- a/packages/networks/boilerplate/src/models/NftTransaction.ts +++ b/packages/networks/boilerplate/src/models/NftTransaction.ts @@ -6,28 +6,28 @@ export class NftTransaction extends ContractTransaction implements NftTransactio /** * @returns Wallet address of the sender of transaction */ - getReceiver(): string { + async getReceiver(): Promise { return 'example' } /** * @returns Transfer amount of the transaction (token) */ - getAmount(): number { + async getAmount(): Promise { return 0 } /** * @returns ID of the NFT */ - getNftId(): number { + async getNftId(): Promise { return 0 } /** * @returns Smart contract address of the transaction */ - getAddress(): string { + async getAddress(): Promise { return 'example' } @@ -37,11 +37,11 @@ export class NftTransaction extends ContractTransaction implements NftTransactio * @param nftId ID of the NFT that will be transferred * @override verifyTransfer() in AssetTransactionInterface */ - verifyTransfer( + async verifyTransfer( direction: AssetDirectionEnum, address: string, nftId: number - ): TransactionStatusEnum { + ): Promise { return TransactionStatusEnum.PENDING } } diff --git a/packages/networks/boilerplate/src/models/TokenTransaction.ts b/packages/networks/boilerplate/src/models/TokenTransaction.ts index c87cd2b..df303a1 100644 --- a/packages/networks/boilerplate/src/models/TokenTransaction.ts +++ b/packages/networks/boilerplate/src/models/TokenTransaction.ts @@ -6,21 +6,21 @@ export class TokenTransaction extends ContractTransaction implements TokenTransa /** * @returns Wallet address of the sender of transaction */ - getReceiver(): string { + async getReceiver(): Promise { return 'example' } /** * @returns Transfer amount of the transaction (token) */ - getAmount(): number { + async getAmount(): Promise { return 0 } /** * @returns Token address of the transaction */ - getAddress(): string { + async getAddress(): Promise { return 'example' } @@ -29,11 +29,11 @@ export class TokenTransaction extends ContractTransaction implements TokenTransa * @param address - Wallet address of the owner or spender of the transaction, dependant on direction * @param amount Amount of tokens that will be approved */ - verifyTransfer( + async verifyTransfer( direction: AssetDirectionEnum, address: string, amount: number - ): TransactionStatusEnum { + ): Promise { return TransactionStatusEnum.PENDING } @@ -42,11 +42,11 @@ export class TokenTransaction extends ContractTransaction implements TokenTransa * @param address - Wallet address of the owner or spender of the transaction, dependant on direction * @param amount Amount of tokens that will be approved */ - verifyApprove( + async verifyApprove( direction: AssetDirectionEnum, address: string, amount: number - ): TransactionStatusEnum { + ): Promise { return TransactionStatusEnum.PENDING } } diff --git a/packages/networks/boilerplate/src/models/Transaction.ts b/packages/networks/boilerplate/src/models/Transaction.ts index 9f7e844..cd4941c 100644 --- a/packages/networks/boilerplate/src/models/Transaction.ts +++ b/packages/networks/boilerplate/src/models/Transaction.ts @@ -14,7 +14,7 @@ export class Transaction implements TransactionInterface { /** * @returns Raw transaction data that is taken by blockchain network via RPC. */ - getData(): object { + async getData(): Promise { return {} } @@ -36,42 +36,42 @@ export class Transaction implements TransactionInterface { /** * @returns Wallet address of the sender of transaction */ - getSender(): string { + async getSender(): Promise { return 'example' } /** * @returns Transaction fee as native coin amount */ - getFee(): number { + async getFee(): Promise { return 0 } /** * @returns Block ID of the transaction */ - getBlockNumber(): number { + async getBlockNumber(): Promise { return 0 } /** * @returns UNIX timestamp of the date that block is added to blockchain */ - getBlockTimestamp(): number { + async getBlockTimestamp(): Promise { return 0 } /** * @returns Confirmation count of the block that transaction is included */ - getBlockConfirmationCount(): number { + async getBlockConfirmationCount(): Promise { return 0 } /** * @returns Status of the transaction */ - getStatus(): TransactionStatusEnum { + async getStatus(): Promise { return TransactionStatusEnum.CONFIRMED } } diff --git a/packages/networks/boilerplate/src/services/TransactionSigner.ts b/packages/networks/boilerplate/src/services/TransactionSigner.ts index b791561..e492e8c 100644 --- a/packages/networks/boilerplate/src/services/TransactionSigner.ts +++ b/packages/networks/boilerplate/src/services/TransactionSigner.ts @@ -22,8 +22,8 @@ export class TransactionSigner implements TransactionSignerInterface { * Sign the transaction * @param privateKey - Transaction data */ - sign(privateKey: string): this { - return this + async sign(privateKey: string): Promise { + return await Promise.resolve(this) } /** From d9da4cc85e81c26d20ad377da50a0101014ce8fa Mon Sep 17 00:00:00 2001 From: Halil Beycan <50718965+BeycanDeveloper@users.noreply.github.com> Date: Sun, 24 Mar 2024 13:38:14 +0800 Subject: [PATCH 005/114] updated --- packages/types/package.json | 2 +- packages/types/src/assets.ts | 34 +++++++++++++++++++++++++++++----- packages/types/src/models.ts | 28 ++++++++++++++-------------- 3 files changed, 44 insertions(+), 20 deletions(-) diff --git a/packages/types/package.json b/packages/types/package.json index 81dca03..74474b5 100644 --- a/packages/types/package.json +++ b/packages/types/package.json @@ -1,6 +1,6 @@ { "name": "@multiplechain/types", - "version": "0.1.14", + "version": "0.1.15", "type": "module", "main": "./src/index.ts", "types": "./src/index.ts", diff --git a/packages/types/src/assets.ts b/packages/types/src/assets.ts index f321cbe..fb94e15 100644 --- a/packages/types/src/assets.ts +++ b/packages/types/src/assets.ts @@ -22,7 +22,7 @@ export interface ContractInterface { * @param args Method parameters * Runs the contract methods dynamically */ - callMethod: (method: string, ...args: any[]) => any + callMethod: (method: string, ...args: any[]) => Promise /** * @param method Method name @@ -30,7 +30,7 @@ export interface ContractInterface { * To get information from called method * @returns Data used in transaction */ - getMethodData: (method: string, ...args: any[]) => any + getMethodData: (method: string, ...args: any[]) => Promise } export interface AssetInterface { @@ -68,10 +68,22 @@ export interface CoinInterface extends AssetInterface { /** * @returns Decimal value of the coin */ - getDecimals: () => number + getDecimals: () => Promise } -export interface TokenInterface extends AssetInterface, ContractInterface { +export interface TokenInterface + extends Omit, + ContractInterface { + /** + * @returns Name of the asset (long name) + */ + getName: () => Promise + + /** + * @returns Symbol of the asset (short name) + */ + getSymbol: () => Promise + /** * @returns Decimal value of the token */ @@ -98,7 +110,19 @@ export interface TokenInterface extends AssetInterface, ContractInterface { allowance: (owner: string, spender: string) => Promise } -export interface NftInterface extends Omit, ContractInterface { +export interface NftInterface + extends Omit, + ContractInterface { + /** + * @returns Name of the asset (long name) + */ + getName: () => Promise + + /** + * @returns Symbol of the asset (short name) + */ + getSymbol: () => Promise + /** * @param nftId ID of the NFT * @returns Wallet address of owner of the NFT diff --git a/packages/types/src/models.ts b/packages/types/src/models.ts index 2682f85..28e0b0d 100644 --- a/packages/types/src/models.ts +++ b/packages/types/src/models.ts @@ -9,7 +9,7 @@ export interface TransactionInterface { /** * @returns Raw transaction data that is taken by blockchain network via RPC. */ - getData: () => object + getData: () => Promise /** * @returns Transaction id from the blockchain network @@ -25,51 +25,51 @@ export interface TransactionInterface { /** * @returns Wallet address of the sender of transaction */ - getSender: () => string + getSender: () => Promise /** * @returns Transaction fee as native coin amount */ - getFee: () => number + getFee: () => Promise /** * @returns Block ID of the transaction */ - getBlockNumber: () => number + getBlockNumber: () => Promise /** * @returns UNIX timestamp of the date that block is added to blockchain */ - getBlockTimestamp: () => number + getBlockTimestamp: () => Promise /** * @returns Block confirmation amount */ - getBlockConfirmationCount: () => number + getBlockConfirmationCount: () => Promise /** * @returns Status of the transaction. */ - getStatus: () => TransactionStatusEnum + getStatus: () => Promise } export interface ContractTransactionInterface extends TransactionInterface { /** * @returns Smart contract address of the transaction */ - getAddress: () => string + getAddress: () => Promise } export interface AssetTransactionInterface extends TransactionInterface { /** * @returns Receiver wallet address of the transaction (asset) */ - getReceiver: () => string + getReceiver: () => Promise /** * @returns Transfer amount of the transaction (coin) */ - getAmount: () => number + getAmount: () => Promise /** * @param direction - Direction of the transaction (asset) @@ -80,7 +80,7 @@ export interface AssetTransactionInterface extends TransactionInterface { direction: AssetDirectionEnum, address: string, amount: number - ) => TransactionStatusEnum + ) => Promise } export interface CoinTransactionInterface extends AssetTransactionInterface {} @@ -97,7 +97,7 @@ export interface TokenTransactionInterface direction: AssetDirectionEnum, address: string, amount: number - ) => TransactionStatusEnum + ) => Promise } export interface NftTransactionInterface @@ -106,7 +106,7 @@ export interface NftTransactionInterface /** * @returns ID of the NFT */ - getNftId: () => number + getNftId: () => Promise /** * @param direction - Direction of the transaction (nft) @@ -118,5 +118,5 @@ export interface NftTransactionInterface direction: AssetDirectionEnum, address: string, nftId: number - ) => TransactionStatusEnum + ) => Promise } From c5412df9b3394a48a5522436a0d41b2b832feec6 Mon Sep 17 00:00:00 2001 From: Halil Beycan <50718965+BeycanDeveloper@users.noreply.github.com> Date: Sun, 24 Mar 2024 13:40:17 +0800 Subject: [PATCH 006/114] updated --- packages/types/package.json | 2 +- packages/types/src/assets.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/types/package.json b/packages/types/package.json index 74474b5..b21bb5f 100644 --- a/packages/types/package.json +++ b/packages/types/package.json @@ -1,6 +1,6 @@ { "name": "@multiplechain/types", - "version": "0.1.15", + "version": "0.1.16", "type": "module", "main": "./src/index.ts", "types": "./src/index.ts", diff --git a/packages/types/src/assets.ts b/packages/types/src/assets.ts index fb94e15..b0e8b63 100644 --- a/packages/types/src/assets.ts +++ b/packages/types/src/assets.ts @@ -68,7 +68,7 @@ export interface CoinInterface extends AssetInterface { /** * @returns Decimal value of the coin */ - getDecimals: () => Promise + getDecimals: () => number } export interface TokenInterface From ae003f14f118c0e7e0b77bc90fb64c0522e12910 Mon Sep 17 00:00:00 2001 From: Halil Beycan <50718965+BeycanDeveloper@users.noreply.github.com> Date: Sun, 24 Mar 2024 13:40:46 +0800 Subject: [PATCH 007/114] updated --- packages/networks/boilerplate/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/networks/boilerplate/package.json b/packages/networks/boilerplate/package.json index be55ceb..d2f3bc9 100644 --- a/packages/networks/boilerplate/package.json +++ b/packages/networks/boilerplate/package.json @@ -36,7 +36,7 @@ "url": "https://github.com/MultipleChain/js/issues" }, "dependencies": { - "@multiplechain/types": "^0.1.13", + "@multiplechain/types": "^0.1.16", "@multiplechain/utils": "^0.1.7" } } \ No newline at end of file From a0ceaba76ac38b0d13b1de5f026c46b8153477af Mon Sep 17 00:00:00 2001 From: Halil Beycan <50718965+BeycanDeveloper@users.noreply.github.com> Date: Sun, 24 Mar 2024 14:26:11 +0800 Subject: [PATCH 008/114] contract is completed --- packages/networks/evm-chains/package.json | 2 +- packages/networks/evm-chains/pnpm-lock.yaml | 8 +++---- .../evm-chains/src/assets/Contract.ts | 20 ++++++++++++---- .../networks/evm-chains/src/assets/NFT.ts | 1 + .../networks/evm-chains/src/assets/Token.ts | 1 + .../evm-chains/src/services/Ethers.ts | 16 ++++++------- .../networks/evm-chains/tests/assets.spec.ts | 23 ++++++++++++++++++- 7 files changed, 52 insertions(+), 19 deletions(-) diff --git a/packages/networks/evm-chains/package.json b/packages/networks/evm-chains/package.json index e8a9dcf..c7b163c 100644 --- a/packages/networks/evm-chains/package.json +++ b/packages/networks/evm-chains/package.json @@ -38,7 +38,7 @@ "url": "https://github.com/MultipleChain/js/issues" }, "dependencies": { - "@multiplechain/types": "^0.1.14", + "@multiplechain/types": "^0.1.16", "@multiplechain/utils": "^0.1.7" } } \ No newline at end of file diff --git a/packages/networks/evm-chains/pnpm-lock.yaml b/packages/networks/evm-chains/pnpm-lock.yaml index 06e65df..0363822 100644 --- a/packages/networks/evm-chains/pnpm-lock.yaml +++ b/packages/networks/evm-chains/pnpm-lock.yaml @@ -6,16 +6,16 @@ settings: dependencies: '@multiplechain/types': - specifier: ^0.1.14 - version: 0.1.14 + specifier: ^0.1.16 + version: 0.1.16 '@multiplechain/utils': specifier: ^0.1.7 version: 0.1.7 packages: - /@multiplechain/types@0.1.14: - resolution: {integrity: sha512-l1OYiodb7zqFkoEb+j60aGFRFkmmQjS/VKAbbXfB+kQo9GgGtK1Y7nGyfQEpcxz7XZh3GSr5k0tMOXFZb6LuQw==} + /@multiplechain/types@0.1.16: + resolution: {integrity: sha512-cTr51snLlwlnoQaxJkA0OPeUp1E4IwjhPL7YQL43ILySWQTyNncwTKKhjF7Rtq4NC192RsD+btlqGscgV5yo4Q==} dev: false /@multiplechain/utils@0.1.7: diff --git a/packages/networks/evm-chains/src/assets/Contract.ts b/packages/networks/evm-chains/src/assets/Contract.ts index fd123ed..94c35e8 100644 --- a/packages/networks/evm-chains/src/assets/Contract.ts +++ b/packages/networks/evm-chains/src/assets/Contract.ts @@ -1,4 +1,8 @@ import type { ContractInterface } from '@multiplechain/types' +import type { Contract as EthersContract } from 'ethers' +import { Provider } from '../services/Provider.ts' + +const { ethers } = Provider.instance export class Contract implements ContractInterface { /** @@ -11,13 +15,19 @@ export class Contract implements ContractInterface { */ abi: object[] + /** + * Ethers contract + */ + ethersContract: EthersContract + /** * @param address Contract address * @param abi Contract ABI */ - constructor(address: string, abi: object[] = []) { + constructor(address: string, abi: object[]) { this.abi = abi this.address = address + this.ethersContract = ethers.contract(address, abi, ethers.jsonRpc) } /** @@ -32,8 +42,8 @@ export class Contract implements ContractInterface { * @param args Method parameters * @returns Method result */ - callMethod(method: string, ...args: any[]): any { - return {} + async callMethod(method: string, ...args: any[]): Promise { + return this.ethersContract[method](...args) // eslint-disable-line } /** @@ -41,7 +51,7 @@ export class Contract implements ContractInterface { * @param args Method parameters * @returns Method data */ - getMethodData(method: string, ...args: any[]): any { - return {} + async getMethodData(method: string, ...args: any[]): Promise { + return this.ethersContract.interface.encodeFunctionData(method, args) } } diff --git a/packages/networks/evm-chains/src/assets/NFT.ts b/packages/networks/evm-chains/src/assets/NFT.ts index 155c666..4d7ebfc 100644 --- a/packages/networks/evm-chains/src/assets/NFT.ts +++ b/packages/networks/evm-chains/src/assets/NFT.ts @@ -1,4 +1,5 @@ import { Contract } from './Contract.ts' +import ERC721 from '../../resources/erc721.json' import { TransactionSigner } from '../services/TransactionSigner.ts' import type { NftInterface, TransactionSignerInterface } from '@multiplechain/types' diff --git a/packages/networks/evm-chains/src/assets/Token.ts b/packages/networks/evm-chains/src/assets/Token.ts index 5853f5f..961b2ce 100644 --- a/packages/networks/evm-chains/src/assets/Token.ts +++ b/packages/networks/evm-chains/src/assets/Token.ts @@ -1,4 +1,5 @@ import { Contract } from './Contract.ts' +import ERC20 from '../../resources/erc20.json' import { TransactionSigner } from '../services/TransactionSigner.ts' import type { TokenInterface, TransactionSignerInterface } from '@multiplechain/types' diff --git a/packages/networks/evm-chains/src/services/Ethers.ts b/packages/networks/evm-chains/src/services/Ethers.ts index 50b1ced..8583ab7 100644 --- a/packages/networks/evm-chains/src/services/Ethers.ts +++ b/packages/networks/evm-chains/src/services/Ethers.ts @@ -45,12 +45,12 @@ export class Ethers { * @param {JsonRpcSigner} signer * @returns {Promise} */ - public async contract( + public contract( address: string, abi: object[], - signer?: JsonRpcSigner - ): Promise { - return new Contract(address, abi, signer ?? (await this.jsonRpc.getSigner())) + signer?: JsonRpcSigner | JsonRpcProvider + ): Contract { + return new Contract(address, abi, signer) } /** @@ -68,12 +68,12 @@ export class Ethers { * @param {JsonRpcSigner} signer * @returns {Promise} */ - public async contractFactory( + public contractFactory( abi: object[], bytecode: string, - signer?: JsonRpcSigner - ): Promise { - return new ContractFactory(abi, bytecode, signer ?? (await this.jsonRpc.getSigner())) + signer?: JsonRpcSigner | JsonRpcProvider + ): ContractFactory { + return new ContractFactory(abi, bytecode, signer) } /** diff --git a/packages/networks/evm-chains/tests/assets.spec.ts b/packages/networks/evm-chains/tests/assets.spec.ts index 687516f..5a41b5b 100644 --- a/packages/networks/evm-chains/tests/assets.spec.ts +++ b/packages/networks/evm-chains/tests/assets.spec.ts @@ -3,6 +3,11 @@ import { describe, it, expect, assert } from 'vitest' import { Coin } from '../src/assets/Coin.ts' import { TransactionSigner } from '../src/services/TransactionSigner.ts' import { Transaction } from '../src/models/Transaction.ts' +import { Contract } from '../src/assets/Contract.ts' +import ERC20 from '../resources/erc20.json' +import { numberToHex } from '@multiplechain/utils' + +const transferTestIsOpen = false const balanceTestAddress = '0x760A4d3D03928D1e8541A7644B34370c1b79aa9F' const tokenTestAddress = '0x4294cb0dD25dC9140B5127f247cBd47Eeb673431' @@ -31,6 +36,7 @@ describe('Coin', () => { }) it('Transfer', async () => { + if (!transferTestIsOpen) return const signer = await coin.transfer( senderTestAddress, receiverTestAddress, @@ -59,7 +65,22 @@ describe('Coin', () => { }) }) -// describe('Contract', () => {}) +describe('Contract', () => { + const contract = new Contract(tokenTestAddress, ERC20) + it('callMethod', async () => { + const name = await contract.callMethod('name') + expect(name).toBe('MyToken') + }) + + it('getMethodData', async () => { + const decimals = await contract.callMethod('decimals') + const hexAmount = numberToHex(tokenBalanceTestAmount, Number(decimals)) + const data = await contract.getMethodData('transfer', receiverTestAddress, hexAmount) + expect(data).toBe( + '0xa9059cbb000000000000000000000000bba4d06d1cef94b35adecfda893523907fdd36de00000000000000000000000000000000000000000000003635c9adc5dea00000' + ) + }) +}) // describe('Token', () => {}) From 7009972bd0adcac90386b3fd027d6414126658c2 Mon Sep 17 00:00:00 2001 From: Halil Beycan <50718965+BeycanDeveloper@users.noreply.github.com> Date: Sun, 24 Mar 2024 14:58:15 +0800 Subject: [PATCH 009/114] token is developing - need fix error: replacement transaction underpriced --- .../networks/evm-chains/src/assets/Coin.ts | 4 +- .../networks/evm-chains/src/assets/Token.ts | 75 ++++++++++++++----- .../evm-chains/src/models/Transaction.ts | 12 +-- .../networks/evm-chains/tests/assets.spec.ts | 57 +++++++++++++- packages/networks/evm-chains/tsconfig.json | 2 +- 5 files changed, 119 insertions(+), 31 deletions(-) diff --git a/packages/networks/evm-chains/src/assets/Coin.ts b/packages/networks/evm-chains/src/assets/Coin.ts index edac33f..e9af99b 100644 --- a/packages/networks/evm-chains/src/assets/Coin.ts +++ b/packages/networks/evm-chains/src/assets/Coin.ts @@ -1,8 +1,8 @@ -import { TransactionSigner } from '../services/TransactionSigner.ts' -import type { CoinInterface, TransactionSignerInterface } from '@multiplechain/types' import { Provider } from '../services/Provider.ts' import { hexToNumber, numberToHex } from '@multiplechain/utils' +import { TransactionSigner } from '../services/TransactionSigner.ts' import type { TransactionData } from '../services/TransactionSigner.ts' +import type { CoinInterface, TransactionSignerInterface } from '@multiplechain/types' const { network, ethers } = Provider.instance diff --git a/packages/networks/evm-chains/src/assets/Token.ts b/packages/networks/evm-chains/src/assets/Token.ts index 961b2ce..4561307 100644 --- a/packages/networks/evm-chains/src/assets/Token.ts +++ b/packages/networks/evm-chains/src/assets/Token.ts @@ -1,50 +1,55 @@ import { Contract } from './Contract.ts' import ERC20 from '../../resources/erc20.json' +import { Provider } from '../services/Provider.ts' import { TransactionSigner } from '../services/TransactionSigner.ts' +import { hexToNumber, numberToHex, toHex } from '@multiplechain/utils' import type { TokenInterface, TransactionSignerInterface } from '@multiplechain/types' +const { network, ethers } = Provider.instance + export class Token extends Contract implements TokenInterface { - /** - * @returns Token name - */ - getName(): string { - return 'example' + constructor(address: string) { + super(address, ERC20) } /** - * @returns Token symbol + * @returns Token name */ - getSymbol(): string { - return 'example' + async getName(): Promise { + return await this.callMethod('name') } /** - * @returns Contract address + * @returns Token symbol */ - getAddress(): string { - return 'example' + async getSymbol(): Promise { + return await this.callMethod('symbol') } /** * @returns Decimal value of the coin */ - getDecimals(): number { - return 18 + async getDecimals(): Promise { + return Number(await this.callMethod('decimals')) } /** * @param owner Wallet address * @returns Wallet balance as currency of TOKEN or COIN assets */ - getBalance(owner: string): number { - return 0 + async getBalance(owner: string): Promise { + const decimals = await this.getDecimals() + const balance = await this.callMethod('balanceOf', owner) + return hexToNumber(balance as string, decimals) } /** * @returns Total supply of the token */ - getTotalSupply(): number { - return 0 + async getTotalSupply(): Promise { + const decimals = await this.getDecimals() + const totalSupply = await this.callMethod('totalSupply') + return hexToNumber(totalSupply as string, decimals) } /** @@ -53,8 +58,40 @@ export class Token extends Contract implements TokenInterface { * @param receiver Receiver wallet address * @param amount Amount of assets that will be transferred */ - transfer(sender: string, receiver: string, amount: number): TransactionSignerInterface { - return new TransactionSigner('example') + async transfer( + sender: string, + receiver: string, + amount: number + ): Promise { + if (amount < 0) { + throw new Error('Invalid amount') + } + + const [balance, decimals] = await Promise.all([this.getBalance(sender), this.getDecimals()]) + + if (amount > balance) { + throw new Error('Insufficient balance') + } + + const hexAmount = numberToHex(amount, decimals) + const [gasPrice, nonce, data, gas] = await Promise.all([ + ethers.getGasPrice(), + ethers.getNonce(sender), + this.getMethodData('transfer', receiver, hexAmount), + this.ethersContract.transfer.estimateGas(receiver, hexAmount, { from: sender }) + ]) + + return new TransactionSigner({ + data, + nonce, + gasPrice, + value: '0x0', + to: receiver, + from: sender, + gas: toHex(gas), + chainId: network.id, + gasLimit: 22000 + }) } /** diff --git a/packages/networks/evm-chains/src/models/Transaction.ts b/packages/networks/evm-chains/src/models/Transaction.ts index 4c470b7..1376e2b 100644 --- a/packages/networks/evm-chains/src/models/Transaction.ts +++ b/packages/networks/evm-chains/src/models/Transaction.ts @@ -54,42 +54,42 @@ export class Transaction implements TransactionInterface { /** * @returns Wallet address of the sender of transaction */ - getSender(): string { + async getSender(): Promise { return 'example' } /** * @returns Transaction fee as native coin amount */ - getFee(): number { + async getFee(): Promise { return 0 } /** * @returns Block ID of the transaction */ - getBlockNumber(): number { + async getBlockNumber(): Promise { return 0 } /** * @returns UNIX timestamp of the date that block is added to blockchain */ - getBlockTimestamp(): number { + async getBlockTimestamp(): Promise { return 0 } /** * @returns Confirmation count of the block that transaction is included */ - getBlockConfirmationCount(): number { + async getBlockConfirmationCount(): Promise { return 0 } /** * @returns Status of the transaction */ - getStatus(): TransactionStatusEnum { + async getStatus(): Promise { return TransactionStatusEnum.CONFIRMED } } diff --git a/packages/networks/evm-chains/tests/assets.spec.ts b/packages/networks/evm-chains/tests/assets.spec.ts index 5a41b5b..e878e8c 100644 --- a/packages/networks/evm-chains/tests/assets.spec.ts +++ b/packages/networks/evm-chains/tests/assets.spec.ts @@ -4,20 +4,22 @@ import { Coin } from '../src/assets/Coin.ts' import { TransactionSigner } from '../src/services/TransactionSigner.ts' import { Transaction } from '../src/models/Transaction.ts' import { Contract } from '../src/assets/Contract.ts' +import { Token } from '../src/assets/Token.ts' import ERC20 from '../resources/erc20.json' import { numberToHex } from '@multiplechain/utils' -const transferTestIsOpen = false +const transferTestIsOpen = true const balanceTestAddress = '0x760A4d3D03928D1e8541A7644B34370c1b79aa9F' -const tokenTestAddress = '0x4294cb0dD25dC9140B5127f247cBd47Eeb673431' const coinBalanceTestAmount = 0.01 const tokenBalanceTestAmount = 1000 const walletPrivateKey = '14bd9af4e87981b37b7b2e8a0d1d249b7fcdb7a3bc579c4c31488842d372c0e9' const senderTestAddress = '0x110600bF0399174520a159ed425f0D272Ff8b459' const receiverTestAddress = '0xbBa4d06D1cEf94b35aDeCfDa893523907fdD36DE' +const tokenTestAddress = '0x4294cb0dD25dC9140B5127f247cBd47Eeb673431' const transferTestAmount = 0.0001 +const tokenTransferTestAmount = 100 describe('Coin', () => { const coin = new Coin() @@ -82,6 +84,55 @@ describe('Contract', () => { }) }) -// describe('Token', () => {}) +describe('Token', () => { + const token = new Token(tokenTestAddress) + it('Name and symbol', async () => { + expect(await token.getName()).toBe('MyToken') + expect(await token.getSymbol()).toBe('MTK') + }) + + it('Decimals', async () => { + expect(await token.getDecimals()).toBe(18) + }) + + it('Balance', async () => { + const balance = await token.getBalance(balanceTestAddress) + expect(balance).toBe(tokenBalanceTestAmount) + }) + + it('Total supply', async () => { + const totalSupply = await token.getTotalSupply() + expect(totalSupply).toBe(1000000) + }) + + it('Transfer', async () => { + if (!transferTestIsOpen) return + const signer = await token.transfer( + senderTestAddress, + receiverTestAddress, + tokenTransferTestAmount + ) + + expect(signer).toBeInstanceOf(TransactionSigner) + + const rawData = signer.getRawData() + + assert.isObject(rawData) + + await signer.sign(walletPrivateKey) + + assert.isString(signer.getSignedData()) + + // const beforeBalance = await token.getBalance(receiverTestAddress) + + const transaction = await signer.send() + + expect(transaction).toBeInstanceOf(Transaction) + + // TODO: Complete after coin transaction verify method is implemented + // const afterBalance = await token.getBalance(receiverTestAddress) + // expect(afterBalance).toBe(beforeBalance + transferTestAmount) + }) +}) // describe('Nft', () => {}) diff --git a/packages/networks/evm-chains/tsconfig.json b/packages/networks/evm-chains/tsconfig.json index 40bb104..ea36f83 100644 --- a/packages/networks/evm-chains/tsconfig.json +++ b/packages/networks/evm-chains/tsconfig.json @@ -7,5 +7,5 @@ "declarationDir": "./dist/types" }, "extends": "../../../tsconfig.json", - "include": ["src", ".eslintrc.json", "tests"] + "include": ["src", ".eslintrc.json", "tests", "resources/*.json"] } From 6e934f3a5a7d502fc91eacc83efe837069db887f Mon Sep 17 00:00:00 2001 From: Halil Beycan <50718965+BeycanDeveloper@users.noreply.github.com> Date: Sun, 24 Mar 2024 16:06:04 +0800 Subject: [PATCH 010/114] methods are created but need fix this error ' const gas = ; // eslint-disable-line --- .../networks/evm-chains/src/assets/Coin.ts | 8 +-- .../evm-chains/src/assets/Contract.ts | 11 ++++ .../networks/evm-chains/src/assets/Token.ts | 58 ++++++++++++++----- .../networks/evm-chains/tests/assets.spec.ts | 55 +++++++++++------- 4 files changed, 91 insertions(+), 41 deletions(-) diff --git a/packages/networks/evm-chains/src/assets/Coin.ts b/packages/networks/evm-chains/src/assets/Coin.ts index e9af99b..b6b74f3 100644 --- a/packages/networks/evm-chains/src/assets/Coin.ts +++ b/packages/networks/evm-chains/src/assets/Coin.ts @@ -2,7 +2,7 @@ import { Provider } from '../services/Provider.ts' import { hexToNumber, numberToHex } from '@multiplechain/utils' import { TransactionSigner } from '../services/TransactionSigner.ts' import type { TransactionData } from '../services/TransactionSigner.ts' -import type { CoinInterface, TransactionSignerInterface } from '@multiplechain/types' +import type { CoinInterface } from '@multiplechain/types' const { network, ethers } = Provider.instance @@ -42,11 +42,7 @@ export class Coin implements CoinInterface { * @param receiver Receiver wallet address * @param amount Amount of assets that will be transferred */ - async transfer( - sender: string, - receiver: string, - amount: number - ): Promise { + async transfer(sender: string, receiver: string, amount: number): Promise { if (amount < 0) { throw new Error('Invalid amount') } diff --git a/packages/networks/evm-chains/src/assets/Contract.ts b/packages/networks/evm-chains/src/assets/Contract.ts index 94c35e8..c1af5bd 100644 --- a/packages/networks/evm-chains/src/assets/Contract.ts +++ b/packages/networks/evm-chains/src/assets/Contract.ts @@ -1,6 +1,7 @@ import type { ContractInterface } from '@multiplechain/types' import type { Contract as EthersContract } from 'ethers' import { Provider } from '../services/Provider.ts' +import { toHex } from '@multiplechain/utils' const { ethers } = Provider.instance @@ -54,4 +55,14 @@ export class Contract implements ContractInterface { async getMethodData(method: string, ...args: any[]): Promise { return this.ethersContract.interface.encodeFunctionData(method, args) } + + /** + * @param method Method name + * @param from Sender wallet address + * @param args Method parameters + * @returns Gas estimate + */ + async getMethodEstimateGas(method: string, from: string, ...args: any[]): Promise { + return toHex(await this.ethersContract[method].estimateGas(...args, { from })) // eslint-disable-line + } } diff --git a/packages/networks/evm-chains/src/assets/Token.ts b/packages/networks/evm-chains/src/assets/Token.ts index 4561307..8632242 100644 --- a/packages/networks/evm-chains/src/assets/Token.ts +++ b/packages/networks/evm-chains/src/assets/Token.ts @@ -2,8 +2,8 @@ import { Contract } from './Contract.ts' import ERC20 from '../../resources/erc20.json' import { Provider } from '../services/Provider.ts' import { TransactionSigner } from '../services/TransactionSigner.ts' -import { hexToNumber, numberToHex, toHex } from '@multiplechain/utils' -import type { TokenInterface, TransactionSignerInterface } from '@multiplechain/types' +import { hexToNumber, numberToHex } from '@multiplechain/utils' +import type { TokenInterface } from '@multiplechain/types' const { network, ethers } = Provider.instance @@ -58,11 +58,7 @@ export class Token extends Contract implements TokenInterface { * @param receiver Receiver wallet address * @param amount Amount of assets that will be transferred */ - async transfer( - sender: string, - receiver: string, - amount: number - ): Promise { + async transfer(sender: string, receiver: string, amount: number): Promise { if (amount < 0) { throw new Error('Invalid amount') } @@ -78,19 +74,19 @@ export class Token extends Contract implements TokenInterface { ethers.getGasPrice(), ethers.getNonce(sender), this.getMethodData('transfer', receiver, hexAmount), - this.ethersContract.transfer.estimateGas(receiver, hexAmount, { from: sender }) + this.getMethodEstimateGas('transfer', sender, receiver, hexAmount) ]) return new TransactionSigner({ + gas, data, nonce, gasPrice, value: '0x0', - to: receiver, from: sender, - gas: toHex(gas), + gasLimit: 800000, chainId: network.id, - gasLimit: 22000 + to: this.getAddress() }) } @@ -100,8 +96,37 @@ export class Token extends Contract implements TokenInterface { * @param spender Address of the spender that will use the tokens of owner * @param amount Amount of the tokens that will be used */ - approve(owner: string, spender: string, amount: number): TransactionSignerInterface { - return new TransactionSigner('example') + async approve(owner: string, spender: string, amount: number): Promise { + if (amount < 0) { + throw new Error('Invalid amount') + } + + const [balance, decimals] = await Promise.all([this.getBalance(owner), this.getDecimals()]) + + if (amount > balance) { + throw new Error('Insufficient balance') + } + + const hexAmount = numberToHex(amount, decimals) + + const [gasPrice, nonce, data, gas] = await Promise.all([ + ethers.getGasPrice(), + ethers.getNonce(owner), + this.getMethodData('approve', spender, hexAmount), + this.getMethodEstimateGas('approve', owner, spender, hexAmount) + ]) + + return new TransactionSigner({ + gas, + data, + nonce, + gasPrice, + value: '0x0', + from: owner, + gasLimit: 800000, + chainId: network.id, + to: this.getAddress() + }) } /** @@ -109,7 +134,10 @@ export class Token extends Contract implements TokenInterface { * @param spender Address of the spender that is using the tokens of owner * @returns Amount of the tokens that is being used by spender */ - allowance(owner: string, spender: string): number { - return 0 + async allowance(owner: string, spender: string): Promise { + return hexToNumber( + (await this.callMethod('allowance', owner, spender)) as string, + await this.getDecimals() + ) } } diff --git a/packages/networks/evm-chains/tests/assets.spec.ts b/packages/networks/evm-chains/tests/assets.spec.ts index e878e8c..0ed745c 100644 --- a/packages/networks/evm-chains/tests/assets.spec.ts +++ b/packages/networks/evm-chains/tests/assets.spec.ts @@ -13,13 +13,26 @@ const transferTestIsOpen = true const balanceTestAddress = '0x760A4d3D03928D1e8541A7644B34370c1b79aa9F' const coinBalanceTestAmount = 0.01 const tokenBalanceTestAmount = 1000 +const tokenApproveTestAmount = 100 -const walletPrivateKey = '14bd9af4e87981b37b7b2e8a0d1d249b7fcdb7a3bc579c4c31488842d372c0e9' +const walletPrivateKey = '0x14bd9af4e87981b37b7b2e8a0d1d249b7fcdb7a3bc579c4c31488842d372c0e9' const senderTestAddress = '0x110600bF0399174520a159ed425f0D272Ff8b459' const receiverTestAddress = '0xbBa4d06D1cEf94b35aDeCfDa893523907fdD36DE' const tokenTestAddress = '0x4294cb0dD25dC9140B5127f247cBd47Eeb673431' const transferTestAmount = 0.0001 -const tokenTransferTestAmount = 100 +const tokenTransferTestAmount = 1 + +const checkSigner = async (signer: TransactionSigner): Promise => { + expect(signer).toBeInstanceOf(TransactionSigner) + + const rawData = signer.getRawData() + + assert.isObject(rawData) + + await signer.sign(walletPrivateKey) + + assert.isString(signer.getSignedData()) +} describe('Coin', () => { const coin = new Coin() @@ -45,15 +58,7 @@ describe('Coin', () => { transferTestAmount ) - expect(signer).toBeInstanceOf(TransactionSigner) - - const rawData = signer.getRawData() - - assert.isObject(rawData) - - await signer.sign(walletPrivateKey) - - assert.isString(signer.getSignedData()) + await checkSigner(signer) // const beforeBalance = await coin.getBalance(receiverTestAddress) @@ -86,6 +91,7 @@ describe('Contract', () => { describe('Token', () => { const token = new Token(tokenTestAddress) + it('Name and symbol', async () => { expect(await token.getName()).toBe('MyToken') expect(await token.getSymbol()).toBe('MTK') @@ -113,25 +119,34 @@ describe('Token', () => { tokenTransferTestAmount ) - expect(signer).toBeInstanceOf(TransactionSigner) + await checkSigner(signer) + + // const beforeBalance = await token.getBalance(receiverTestAddress) - const rawData = signer.getRawData() + const transaction = await signer.send() - assert.isObject(rawData) + expect(transaction).toBeInstanceOf(Transaction) - await signer.sign(walletPrivateKey) + // TODO: Complete after token transaction verify method is implemented + // const afterBalance = await token.getBalance(receiverTestAddress) + // expect(afterBalance).toBe(beforeBalance + transferTestAmount) + }) - assert.isString(signer.getSignedData()) + it('Approve and Allowance', async () => { + const signer = await token.approve( + senderTestAddress, + receiverTestAddress, + tokenApproveTestAmount + ) - // const beforeBalance = await token.getBalance(receiverTestAddress) + await checkSigner(signer) const transaction = await signer.send() expect(transaction).toBeInstanceOf(Transaction) - // TODO: Complete after coin transaction verify method is implemented - // const afterBalance = await token.getBalance(receiverTestAddress) - // expect(afterBalance).toBe(beforeBalance + transferTestAmount) + // TODO: complete after token transaction verify method is implemented + // expect(await token.allowance(senderTestAddress, receiverTestAddress)).toBe(tokenApproveTestAmount) }) }) From 8d8dfc663ce358354d085868c9ffc2d85632368d Mon Sep 17 00:00:00 2001 From: Halil Beycan <50718965+BeycanDeveloper@users.noreply.github.com> Date: Mon, 25 Mar 2024 11:24:44 +0800 Subject: [PATCH 011/114] added wait method for transaction --- packages/types/package.json | 2 +- packages/types/src/models.ts | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/packages/types/package.json b/packages/types/package.json index b21bb5f..6a6cc11 100644 --- a/packages/types/package.json +++ b/packages/types/package.json @@ -1,6 +1,6 @@ { "name": "@multiplechain/types", - "version": "0.1.16", + "version": "0.1.17", "type": "module", "main": "./src/index.ts", "types": "./src/index.ts", diff --git a/packages/types/src/models.ts b/packages/types/src/models.ts index 28e0b0d..767d224 100644 --- a/packages/types/src/models.ts +++ b/packages/types/src/models.ts @@ -6,6 +6,11 @@ export interface TransactionInterface { */ id: string + /** + * @returns Promise of the transaction status + */ + wait: () => Promise + /** * @returns Raw transaction data that is taken by blockchain network via RPC. */ From e20c3203edf0d34d4f6a29c348663231c3d7292c Mon Sep 17 00:00:00 2001 From: Halil Beycan <50718965+BeycanDeveloper@users.noreply.github.com> Date: Mon, 25 Mar 2024 11:51:55 +0800 Subject: [PATCH 012/114] updated --- packages/networks/boilerplate/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/networks/boilerplate/package.json b/packages/networks/boilerplate/package.json index d2f3bc9..fd94ceb 100644 --- a/packages/networks/boilerplate/package.json +++ b/packages/networks/boilerplate/package.json @@ -36,7 +36,7 @@ "url": "https://github.com/MultipleChain/js/issues" }, "dependencies": { - "@multiplechain/types": "^0.1.16", + "@multiplechain/types": "^0.1.17", "@multiplechain/utils": "^0.1.7" } } \ No newline at end of file From a2063ab83d377f5c9009dc7997aee0b28587ae05 Mon Sep 17 00:00:00 2001 From: Halil Beycan <50718965+BeycanDeveloper@users.noreply.github.com> Date: Mon, 25 Mar 2024 11:56:15 +0800 Subject: [PATCH 013/114] added TODO note --- packages/networks/evm-chains/src/models/Transaction.ts | 5 +++++ .../networks/evm-chains/src/services/TransactionSigner.ts | 8 ++++---- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/packages/networks/evm-chains/src/models/Transaction.ts b/packages/networks/evm-chains/src/models/Transaction.ts index 1376e2b..ca1c460 100644 --- a/packages/networks/evm-chains/src/models/Transaction.ts +++ b/packages/networks/evm-chains/src/models/Transaction.ts @@ -36,6 +36,11 @@ export class Transaction implements TransactionInterface { } } + async wait(): Promise { + // TODO: will complete this method first + return await this.getStatus() + } + /** * @returns Transaction id from the blockchain network * this can be different names like txid, hash, signature etc. diff --git a/packages/networks/evm-chains/src/services/TransactionSigner.ts b/packages/networks/evm-chains/src/services/TransactionSigner.ts index db23e8b..d002d0d 100644 --- a/packages/networks/evm-chains/src/services/TransactionSigner.ts +++ b/packages/networks/evm-chains/src/services/TransactionSigner.ts @@ -1,7 +1,7 @@ -import type { TransactionSignerInterface, TransactionInterface } from '@multiplechain/types' import { Provider } from '../services/Provider.ts' -import type { TransactionRequest, Wallet } from 'ethers' import { Transaction } from '../models/Transaction.ts' +import type { TransactionRequest, Wallet } from 'ethers' +import type { TransactionSignerInterface } from '@multiplechain/types' export interface TransactionData extends TransactionRequest { gas?: string @@ -46,9 +46,9 @@ export class TransactionSigner implements TransactionSignerInterface { * Send the transaction to the blockchain network * @returns Promise of the transaction */ - async send(): Promise { + async send(): Promise { return new Transaction( - (await ethers.jsonRpc.send('eth_sendRawTransaction', [this.signedData])).hash as string + (await ethers.jsonRpc.send('eth_sendRawTransaction', [this.signedData])) as string ) } From a3a432e8e446e058ff0ca7cde2a728a620765b56 Mon Sep 17 00:00:00 2001 From: Halil Beycan <50718965+BeycanDeveloper@users.noreply.github.com> Date: Mon, 25 Mar 2024 18:25:52 +0800 Subject: [PATCH 014/114] added string definations for enums --- packages/types/package.json | 2 +- packages/types/src/enums.ts | 22 +++++++++++----------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/packages/types/package.json b/packages/types/package.json index 6a6cc11..3b060ba 100644 --- a/packages/types/package.json +++ b/packages/types/package.json @@ -1,6 +1,6 @@ { "name": "@multiplechain/types", - "version": "0.1.17", + "version": "0.1.18", "type": "module", "main": "./src/index.ts", "types": "./src/index.ts", diff --git a/packages/types/src/enums.ts b/packages/types/src/enums.ts index bad56da..6979bf0 100644 --- a/packages/types/src/enums.ts +++ b/packages/types/src/enums.ts @@ -2,8 +2,8 @@ * Asset transactions (COIN, TOKEN, NFT) has two directions */ export enum AssetDirectionEnum { - INCOMING, - OUTGOING + INCOMING = 'INCOMING', + OUTGOING = 'OUTGOING' } /** @@ -11,12 +11,12 @@ export enum AssetDirectionEnum { * COIN, TOKEN, and NFT transactions are called ASSET transactions */ export enum TransactionTypeEnum { - GENERAL, - CONTRACT, - ASSET, - COIN, - TOKEN, - NFT + GENERAL = 'GENERAL', + CONTRACT = 'CONTRACT', + ASSET = 'ASSET', + COIN = 'COIN', + TOKEN = 'TOKEN', + NFT = 'NFT' } /** @@ -26,7 +26,7 @@ export enum TransactionTypeEnum { * CONFIRMED --> When a transaction is confirmed */ export enum TransactionStatusEnum { - FAILED, - PENDING, - CONFIRMED + FAILED = 'FAILED', + PENDING = 'PENDING', + CONFIRMED = 'CONFIRMED' } From 5e27c3ac1817919784799ac10b91e205c04be16f Mon Sep 17 00:00:00 2001 From: Halil Beycan <50718965+BeycanDeveloper@users.noreply.github.com> Date: Mon, 25 Mar 2024 18:27:20 +0800 Subject: [PATCH 015/114] completed wait method for transaction model --- packages/networks/boilerplate/package.json | 2 +- packages/networks/evm-chains/.eslintrc.json | 15 ++++-- packages/networks/evm-chains/package.json | 2 +- packages/networks/evm-chains/pnpm-lock.yaml | 8 +-- .../evm-chains/src/models/Transaction.ts | 49 ++++++++++++++++--- 5 files changed, 57 insertions(+), 19 deletions(-) diff --git a/packages/networks/boilerplate/package.json b/packages/networks/boilerplate/package.json index fd94ceb..ab22a6f 100644 --- a/packages/networks/boilerplate/package.json +++ b/packages/networks/boilerplate/package.json @@ -36,7 +36,7 @@ "url": "https://github.com/MultipleChain/js/issues" }, "dependencies": { - "@multiplechain/types": "^0.1.17", + "@multiplechain/types": "^0.1.18", "@multiplechain/utils": "^0.1.7" } } \ No newline at end of file diff --git a/packages/networks/evm-chains/.eslintrc.json b/packages/networks/evm-chains/.eslintrc.json index b62472f..e7ed887 100644 --- a/packages/networks/evm-chains/.eslintrc.json +++ b/packages/networks/evm-chains/.eslintrc.json @@ -1,7 +1,12 @@ { - "extends": [ - "plugin:require-extensions/recommended", - "../../../.eslintrc.json" - ], + "rules": { + "@typescript-eslint/no-misused-promises": [ + "error", + { + "checksVoidReturn": false + } + ] + }, + "extends": ["plugin:require-extensions/recommended", "../../../.eslintrc.json"], "plugins": ["require-extensions"] -} \ No newline at end of file +} diff --git a/packages/networks/evm-chains/package.json b/packages/networks/evm-chains/package.json index c7b163c..b4f5237 100644 --- a/packages/networks/evm-chains/package.json +++ b/packages/networks/evm-chains/package.json @@ -38,7 +38,7 @@ "url": "https://github.com/MultipleChain/js/issues" }, "dependencies": { - "@multiplechain/types": "^0.1.16", + "@multiplechain/types": "^0.1.18", "@multiplechain/utils": "^0.1.7" } } \ No newline at end of file diff --git a/packages/networks/evm-chains/pnpm-lock.yaml b/packages/networks/evm-chains/pnpm-lock.yaml index 0363822..50530f6 100644 --- a/packages/networks/evm-chains/pnpm-lock.yaml +++ b/packages/networks/evm-chains/pnpm-lock.yaml @@ -6,16 +6,16 @@ settings: dependencies: '@multiplechain/types': - specifier: ^0.1.16 - version: 0.1.16 + specifier: ^0.1.18 + version: 0.1.18 '@multiplechain/utils': specifier: ^0.1.7 version: 0.1.7 packages: - /@multiplechain/types@0.1.16: - resolution: {integrity: sha512-cTr51snLlwlnoQaxJkA0OPeUp1E4IwjhPL7YQL43ILySWQTyNncwTKKhjF7Rtq4NC192RsD+btlqGscgV5yo4Q==} + /@multiplechain/types@0.1.18: + resolution: {integrity: sha512-HToqt7TUG5BCQzoHT1NOS69KG/CS+JWFi4+VF/4xf4v8dmbHSybNnN8727Nnn6oGPv9g6fKcAvR4306xxZkSJg==} dev: false /@multiplechain/utils@0.1.7: diff --git a/packages/networks/evm-chains/src/models/Transaction.ts b/packages/networks/evm-chains/src/models/Transaction.ts index ca1c460..379b539 100644 --- a/packages/networks/evm-chains/src/models/Transaction.ts +++ b/packages/networks/evm-chains/src/models/Transaction.ts @@ -2,6 +2,13 @@ import type { TransactionInterface } from '@multiplechain/types' import { TransactionStatusEnum } from '@multiplechain/types' import { Provider } from '../services/Provider.ts' +import type { TransactionReceipt, TransactionResponse } from 'ethers' + +interface TransactionData { + response: TransactionResponse + receipt: TransactionReceipt +} + export class Transaction implements TransactionInterface { /** * Each transaction has its own unique ID defined by the user @@ -21,12 +28,14 @@ export class Transaction implements TransactionInterface { /** * @returns Raw transaction data that is taken by blockchain network via RPC. */ - async getData(): Promise { + async getData(): Promise { try { - const data = (await this.provider.ethers.getTransaction(this.id)) ?? {} - const receipt = (await this.provider.ethers.getTransactionReceipt(this.id)) ?? {} - const result: object = { ...data, ...receipt } - return Object.keys(result).length !== 0 ? result : null + const response = await this.provider.ethers.getTransaction(this.id) + const receipt = await this.provider.ethers.getTransactionReceipt(this.id) + if (response === null || receipt === null) { + return null + } + return { response, receipt } } catch (error) { const e = error as Error if (String(e.message).includes('timeout')) { @@ -37,8 +46,22 @@ export class Transaction implements TransactionInterface { } async wait(): Promise { - // TODO: will complete this method first - return await this.getStatus() + return await new Promise((resolve, reject) => { + const check = async (): Promise => { + try { + const status = await this.getStatus() + if (status === TransactionStatusEnum.CONFIRMED) { + resolve(TransactionStatusEnum.CONFIRMED) + } else if (status === TransactionStatusEnum.FAILED) { + reject(TransactionStatusEnum.FAILED) + } + setTimeout(check, 4000) + } catch (error) { + reject(TransactionStatusEnum.FAILED) + } + } + check() // eslint-disable-line @typescript-eslint/no-floating-promises + }) } /** @@ -95,6 +118,16 @@ export class Transaction implements TransactionInterface { * @returns Status of the transaction */ async getStatus(): Promise { - return TransactionStatusEnum.CONFIRMED + const data = await this.getData() + if (data === null) { + return TransactionStatusEnum.PENDING + } else if (data.response.blockNumber !== null) { + if (data.receipt.status === 1) { + return TransactionStatusEnum.CONFIRMED + } else { + return TransactionStatusEnum.FAILED + } + } + return TransactionStatusEnum.PENDING } } From b5ce0a3dd5e41c7430c061956d3c30f382be5ad1 Mon Sep 17 00:00:00 2001 From: Halil Beycan <50718965+BeycanDeveloper@users.noreply.github.com> Date: Tue, 26 Mar 2024 00:26:31 +0800 Subject: [PATCH 016/114] added new methods --- packages/utils/package.json | 2 +- packages/utils/src/index.ts | 22 ++++++++++++++++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/packages/utils/package.json b/packages/utils/package.json index 855bd4f..2f06528 100644 --- a/packages/utils/package.json +++ b/packages/utils/package.json @@ -1,6 +1,6 @@ { "name": "@multiplechain/utils", - "version": "0.1.7", + "version": "0.1.8", "type": "module", "main": "./src/index.ts", "types": "./src/index.ts", diff --git a/packages/utils/src/index.ts b/packages/utils/src/index.ts index f42a279..da1aedc 100644 --- a/packages/utils/src/index.ts +++ b/packages/utils/src/index.ts @@ -88,4 +88,26 @@ export const isNumeric = (value: string | number): boolean => { return !isNaN(Number(value)) } +/** + * Get the number of decimal places + */ +export const getDecimalPlaces = (num: number): number => { + const match = ('' + num).match(/(?:\.(\d+))?(?:[eE]([+-]?\d+))?$/) + if (match === null) { + return num + } else { + return Math.max( + 0, + // Number of digits right of decimal point. + (match[1] !== undefined && match[1] !== null ? match[1].length : 0) - + // Adjust for scientific notation. + (match[2] !== undefined && match[2] !== null ? +match[2] : 0) + ) + } +} + +export const fixFloat = (num: number): number => { + return parseFloat(num.toFixed(getDecimalPlaces(num))) +} + export { toHex } From ce4a0138629870f648db09a6c359ea69b31d6c38 Mon Sep 17 00:00:00 2001 From: Halil Beycan <50718965+BeycanDeveloper@users.noreply.github.com> Date: Tue, 26 Mar 2024 00:35:23 +0800 Subject: [PATCH 017/114] ready for tests --- packages/networks/evm-chains/package.json | 2 +- packages/networks/evm-chains/pnpm-lock.yaml | 8 ++-- .../networks/evm-chains/src/assets/Coin.ts | 5 +- .../evm-chains/src/assets/Contract.ts | 5 +- .../networks/evm-chains/src/assets/Token.ts | 10 ++-- .../evm-chains/src/models/Transaction.ts | 18 +++----- .../evm-chains/src/services/Ethers.ts | 8 ++-- .../src/services/TransactionSigner.ts | 6 +-- .../networks/evm-chains/tests/assets.spec.ts | 46 +++++++++---------- 9 files changed, 49 insertions(+), 59 deletions(-) diff --git a/packages/networks/evm-chains/package.json b/packages/networks/evm-chains/package.json index b4f5237..1e91902 100644 --- a/packages/networks/evm-chains/package.json +++ b/packages/networks/evm-chains/package.json @@ -39,6 +39,6 @@ }, "dependencies": { "@multiplechain/types": "^0.1.18", - "@multiplechain/utils": "^0.1.7" + "@multiplechain/utils": "^0.1.8" } } \ No newline at end of file diff --git a/packages/networks/evm-chains/pnpm-lock.yaml b/packages/networks/evm-chains/pnpm-lock.yaml index 50530f6..f9666d7 100644 --- a/packages/networks/evm-chains/pnpm-lock.yaml +++ b/packages/networks/evm-chains/pnpm-lock.yaml @@ -9,8 +9,8 @@ dependencies: specifier: ^0.1.18 version: 0.1.18 '@multiplechain/utils': - specifier: ^0.1.7 - version: 0.1.7 + specifier: ^0.1.8 + version: 0.1.8 packages: @@ -18,8 +18,8 @@ packages: resolution: {integrity: sha512-HToqt7TUG5BCQzoHT1NOS69KG/CS+JWFi4+VF/4xf4v8dmbHSybNnN8727Nnn6oGPv9g6fKcAvR4306xxZkSJg==} dev: false - /@multiplechain/utils@0.1.7: - resolution: {integrity: sha512-I29JEiL+OTs6I6Lb4dTSsshcODttgO8oeCIP0xvJnkebIHz8ODyNG6rnQtUV/cOHhf4S12ZBkLN4FNJFuy/Mmw==} + /@multiplechain/utils@0.1.8: + resolution: {integrity: sha512-AJxrAiHm+hoTOgeCFL6rXHV/EeDpmXe9KLtwNOQx8Pnqbz1sIiHEedhSGohkQsJddq8/e1d0MCBGqi7GFmtqSw==} dependencies: bignumber.js: 9.1.2 web3-utils: 4.2.0 diff --git a/packages/networks/evm-chains/src/assets/Coin.ts b/packages/networks/evm-chains/src/assets/Coin.ts index b6b74f3..1085341 100644 --- a/packages/networks/evm-chains/src/assets/Coin.ts +++ b/packages/networks/evm-chains/src/assets/Coin.ts @@ -61,16 +61,15 @@ export class Coin implements CoinInterface { value: hexAmount } - const [gasPrice, nonce, gas] = await Promise.all([ + const [gasPrice, nonce, gasLimit] = await Promise.all([ ethers.getGasPrice(), ethers.getNonce(sender), ethers.getEstimateGas(txData) ]) - txData.gas = gas txData.nonce = nonce txData.gasPrice = gasPrice - txData.gasLimit = 21000 + txData.gasLimit = gasLimit return new TransactionSigner(txData) } diff --git a/packages/networks/evm-chains/src/assets/Contract.ts b/packages/networks/evm-chains/src/assets/Contract.ts index c1af5bd..46627b4 100644 --- a/packages/networks/evm-chains/src/assets/Contract.ts +++ b/packages/networks/evm-chains/src/assets/Contract.ts @@ -1,7 +1,6 @@ import type { ContractInterface } from '@multiplechain/types' import type { Contract as EthersContract } from 'ethers' import { Provider } from '../services/Provider.ts' -import { toHex } from '@multiplechain/utils' const { ethers } = Provider.instance @@ -62,7 +61,7 @@ export class Contract implements ContractInterface { * @param args Method parameters * @returns Gas estimate */ - async getMethodEstimateGas(method: string, from: string, ...args: any[]): Promise { - return toHex(await this.ethersContract[method].estimateGas(...args, { from })) // eslint-disable-line + async getMethodEstimateGas(method: string, from: string, ...args: any[]): Promise { + return Number(await this.ethersContract[method].estimateGas(...args, { from })) // eslint-disable-line } } diff --git a/packages/networks/evm-chains/src/assets/Token.ts b/packages/networks/evm-chains/src/assets/Token.ts index 8632242..260a322 100644 --- a/packages/networks/evm-chains/src/assets/Token.ts +++ b/packages/networks/evm-chains/src/assets/Token.ts @@ -70,7 +70,7 @@ export class Token extends Contract implements TokenInterface { } const hexAmount = numberToHex(amount, decimals) - const [gasPrice, nonce, data, gas] = await Promise.all([ + const [gasPrice, nonce, data, gasLimit] = await Promise.all([ ethers.getGasPrice(), ethers.getNonce(sender), this.getMethodData('transfer', receiver, hexAmount), @@ -78,13 +78,12 @@ export class Token extends Contract implements TokenInterface { ]) return new TransactionSigner({ - gas, data, nonce, gasPrice, + gasLimit, value: '0x0', from: sender, - gasLimit: 800000, chainId: network.id, to: this.getAddress() }) @@ -109,7 +108,7 @@ export class Token extends Contract implements TokenInterface { const hexAmount = numberToHex(amount, decimals) - const [gasPrice, nonce, data, gas] = await Promise.all([ + const [gasPrice, nonce, data, gasLimit] = await Promise.all([ ethers.getGasPrice(), ethers.getNonce(owner), this.getMethodData('approve', spender, hexAmount), @@ -117,13 +116,12 @@ export class Token extends Contract implements TokenInterface { ]) return new TransactionSigner({ - gas, data, nonce, gasPrice, + gasLimit, value: '0x0', from: owner, - gasLimit: 800000, chainId: network.id, to: this.getAddress() }) diff --git a/packages/networks/evm-chains/src/models/Transaction.ts b/packages/networks/evm-chains/src/models/Transaction.ts index 379b539..8d60884 100644 --- a/packages/networks/evm-chains/src/models/Transaction.ts +++ b/packages/networks/evm-chains/src/models/Transaction.ts @@ -1,9 +1,10 @@ -import type { TransactionInterface } from '@multiplechain/types' -import { TransactionStatusEnum } from '@multiplechain/types' import { Provider } from '../services/Provider.ts' - +import { TransactionStatusEnum } from '@multiplechain/types' +import type { TransactionInterface } from '@multiplechain/types' import type { TransactionReceipt, TransactionResponse } from 'ethers' +const { ethers } = Provider.instance + interface TransactionData { response: TransactionResponse receipt: TransactionReceipt @@ -15,14 +16,8 @@ export class Transaction implements TransactionInterface { */ id: string - /** - * Provider instance - */ - private readonly provider: Provider - constructor(id: string) { this.id = id - this.provider = Provider.instance } /** @@ -30,8 +25,8 @@ export class Transaction implements TransactionInterface { */ async getData(): Promise { try { - const response = await this.provider.ethers.getTransaction(this.id) - const receipt = await this.provider.ethers.getTransactionReceipt(this.id) + const response = await ethers.getTransaction(this.id) + const receipt = await ethers.getTransactionReceipt(this.id) if (response === null || receipt === null) { return null } @@ -50,6 +45,7 @@ export class Transaction implements TransactionInterface { const check = async (): Promise => { try { const status = await this.getStatus() + console.log(status) if (status === TransactionStatusEnum.CONFIRMED) { resolve(TransactionStatusEnum.CONFIRMED) } else if (status === TransactionStatusEnum.FAILED) { diff --git a/packages/networks/evm-chains/src/services/Ethers.ts b/packages/networks/evm-chains/src/services/Ethers.ts index 8583ab7..3123cd6 100644 --- a/packages/networks/evm-chains/src/services/Ethers.ts +++ b/packages/networks/evm-chains/src/services/Ethers.ts @@ -8,8 +8,6 @@ import type { import { Wallet, Contract, ContractFactory, JsonRpcProvider, WebSocketProvider } from 'ethers' -import { toHex } from '@multiplechain/utils' - import type { EvmNetworkConfigInterface } from './Provider.ts' import type { TransactionData } from '../services/TransactionSigner.ts' @@ -78,10 +76,10 @@ export class Ethers { /** * @param {Object} data - * @returns {Promise} + * @returns {Promise} */ - public async getEstimateGas(data: TransactionData): Promise { - return toHex((await this.jsonRpcProvider.estimateGas(data)).toString()) + public async getEstimateGas(data: TransactionData): Promise { + return Number(await this.jsonRpcProvider.estimateGas(data)) } /** diff --git a/packages/networks/evm-chains/src/services/TransactionSigner.ts b/packages/networks/evm-chains/src/services/TransactionSigner.ts index d002d0d..0ae63df 100644 --- a/packages/networks/evm-chains/src/services/TransactionSigner.ts +++ b/packages/networks/evm-chains/src/services/TransactionSigner.ts @@ -1,10 +1,10 @@ import { Provider } from '../services/Provider.ts' import { Transaction } from '../models/Transaction.ts' -import type { TransactionRequest, Wallet } from 'ethers' +import type { TransactionRequest, Wallet, BigNumberish } from 'ethers' import type { TransactionSignerInterface } from '@multiplechain/types' export interface TransactionData extends TransactionRequest { - gas?: string + gas?: BigNumberish } const { ethers } = Provider.instance @@ -46,7 +46,7 @@ export class TransactionSigner implements TransactionSignerInterface { * Send the transaction to the blockchain network * @returns Promise of the transaction */ - async send(): Promise { + async send(): Promise { return new Transaction( (await ethers.jsonRpc.send('eth_sendRawTransaction', [this.signedData])) as string ) diff --git a/packages/networks/evm-chains/tests/assets.spec.ts b/packages/networks/evm-chains/tests/assets.spec.ts index 0ed745c..1ff2aaf 100644 --- a/packages/networks/evm-chains/tests/assets.spec.ts +++ b/packages/networks/evm-chains/tests/assets.spec.ts @@ -1,12 +1,13 @@ import { describe, it, expect, assert } from 'vitest' +import ERC20 from '../resources/erc20.json' import { Coin } from '../src/assets/Coin.ts' -import { TransactionSigner } from '../src/services/TransactionSigner.ts' -import { Transaction } from '../src/models/Transaction.ts' -import { Contract } from '../src/assets/Contract.ts' import { Token } from '../src/assets/Token.ts' -import ERC20 from '../resources/erc20.json' import { numberToHex } from '@multiplechain/utils' +import { Contract } from '../src/assets/Contract.ts' +import { Transaction } from '../src/models/Transaction.ts' +import { TransactionStatusEnum } from '@multiplechain/types' +import { TransactionSigner } from '../src/services/TransactionSigner.ts' const transferTestIsOpen = true @@ -34,6 +35,12 @@ const checkSigner = async (signer: TransactionSigner): Promise => { assert.isString(signer.getSignedData()) } +const checkTx = async (transaction: Transaction): Promise => { + expect(transaction).toBeInstanceOf(Transaction) + await transaction.wait() + expect(await transaction.getStatus()).toBe(TransactionStatusEnum.CONFIRMED) +} + describe('Coin', () => { const coin = new Coin() it('Name and symbol', () => { @@ -60,15 +67,12 @@ describe('Coin', () => { await checkSigner(signer) - // const beforeBalance = await coin.getBalance(receiverTestAddress) + const beforeBalance = await coin.getBalance(receiverTestAddress) - const transaction = await signer.send() + await checkTx(await signer.send()) - expect(transaction).toBeInstanceOf(Transaction) - - // TODO: Complete after coin transaction verify method is implemented - // const afterBalance = await coin.getBalance(receiverTestAddress) - // expect(afterBalance).toBe(beforeBalance + transferTestAmount) + const afterBalance = await coin.getBalance(receiverTestAddress) + expect(afterBalance).toBe(beforeBalance + transferTestAmount) }) }) @@ -121,15 +125,12 @@ describe('Token', () => { await checkSigner(signer) - // const beforeBalance = await token.getBalance(receiverTestAddress) - - const transaction = await signer.send() + const beforeBalance = await token.getBalance(receiverTestAddress) - expect(transaction).toBeInstanceOf(Transaction) + await checkTx(await signer.send()) - // TODO: Complete after token transaction verify method is implemented - // const afterBalance = await token.getBalance(receiverTestAddress) - // expect(afterBalance).toBe(beforeBalance + transferTestAmount) + const afterBalance = await token.getBalance(receiverTestAddress) + expect(afterBalance).toBe(beforeBalance + transferTestAmount) }) it('Approve and Allowance', async () => { @@ -141,12 +142,11 @@ describe('Token', () => { await checkSigner(signer) - const transaction = await signer.send() + await checkTx(await signer.send()) - expect(transaction).toBeInstanceOf(Transaction) - - // TODO: complete after token transaction verify method is implemented - // expect(await token.allowance(senderTestAddress, receiverTestAddress)).toBe(tokenApproveTestAmount) + expect(await token.allowance(senderTestAddress, receiverTestAddress)).toBe( + tokenApproveTestAmount + ) }) }) From f50e63801424137af7b56e2e5586b3277fbbcdca Mon Sep 17 00:00:00 2001 From: Halil Beycan <50718965+BeycanDeveloper@users.noreply.github.com> Date: Tue, 26 Mar 2024 00:35:36 +0800 Subject: [PATCH 018/114] updated --- packages/networks/boilerplate/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/networks/boilerplate/package.json b/packages/networks/boilerplate/package.json index ab22a6f..ff7c1de 100644 --- a/packages/networks/boilerplate/package.json +++ b/packages/networks/boilerplate/package.json @@ -37,6 +37,6 @@ }, "dependencies": { "@multiplechain/types": "^0.1.18", - "@multiplechain/utils": "^0.1.7" + "@multiplechain/utils": "^0.1.8" } } \ No newline at end of file From 33da9a74bfb0a6dcd178db041b7561622024abfe Mon Sep 17 00:00:00 2001 From: Halil Beycan <50718965+BeycanDeveloper@users.noreply.github.com> Date: Tue, 26 Mar 2024 17:27:03 +0800 Subject: [PATCH 019/114] added error types --- packages/types/package.json | 2 +- packages/types/src/enums.ts | 22 ++++++++++++++++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/packages/types/package.json b/packages/types/package.json index 3b060ba..31d93c6 100644 --- a/packages/types/package.json +++ b/packages/types/package.json @@ -1,6 +1,6 @@ { "name": "@multiplechain/types", - "version": "0.1.18", + "version": "0.1.19", "type": "module", "main": "./src/index.ts", "types": "./src/index.ts", diff --git a/packages/types/src/enums.ts b/packages/types/src/enums.ts index 6979bf0..ea1d409 100644 --- a/packages/types/src/enums.ts +++ b/packages/types/src/enums.ts @@ -30,3 +30,25 @@ export enum TransactionStatusEnum { PENDING = 'PENDING', CONFIRMED = 'CONFIRMED' } + +export enum ErrorTypeEnum { + RPC_TIMEOUT = 'RPC_TIMEOUT', + RPC_REQUEST_ERROR = 'RPC_REQUEST_ERROR', + RPC_ACCESS_DENIED = 'RPC_ACCESS_DENIED', + UNACCEPTED_CHAIN = 'UNACCEPTED_CHAIN', + INSUFFICIENT_BALANCE = 'INSUFFICIENT_BALANCE', + INVALID_AMOUNT = 'INVALID_AMOUNT', + INVALID_ADDRESS = 'INVALID_ADDRESS', + INVALID_PRIVATE_KEY = 'INVALID_PRIVATE_KEY', + INVALID_PUBLIC_KEY = 'INVALID_PUBLIC_KEY', + INVALID_TRANSACTION_ID = 'INVALID_TRANSACTION_ID', + PROVIDER_IS_NOT_INITIALIZED = 'PROVIDER_IS_NOT_INITIALIZED', + PROVIDER_IS_ALREADY_INITIALIZED = 'PROVIDER_IS_ALREADY_INITIALIZED', + WALLET_ALREADY_PROCESSING = 'WALLET_ALREADY_PROCESSING', + WALLET_CONNECT_REJECTED = 'WALLET_CONNECT_REJECTED', + WALLET_REQUEST_REJECTED = 'WALLET_REQUEST_REJECTED', + WALLET_CONNECTION_FAILED = 'WALLET_CONNECTION_FAILED', + WALLET_CONNECTION_TIMEOUT = 'WALLET_CONNECTION_TIMEOUT', + TRANSACTION_CREATION_FAILED = 'TRANSACTION_CREATION_FAILED', + CLOSED_WALLETCONNECT_MODAL = 'CLOSED_WALLETCONNECT_MODAL' +} From f518e0ea7adc1b20a3521a593ba432e2e45b9dd2 Mon Sep 17 00:00:00 2001 From: Halil Beycan <50718965+BeycanDeveloper@users.noreply.github.com> Date: Tue, 26 Mar 2024 17:47:50 +0800 Subject: [PATCH 020/114] added new method --- packages/utils/package.json | 2 +- packages/utils/src/index.ts | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/packages/utils/package.json b/packages/utils/package.json index 2f06528..5b6b3e5 100644 --- a/packages/utils/package.json +++ b/packages/utils/package.json @@ -1,6 +1,6 @@ { "name": "@multiplechain/utils", - "version": "0.1.8", + "version": "0.1.9", "type": "module", "main": "./src/index.ts", "types": "./src/index.ts", diff --git a/packages/utils/src/index.ts b/packages/utils/src/index.ts index da1aedc..20e9de7 100644 --- a/packages/utils/src/index.ts +++ b/packages/utils/src/index.ts @@ -110,4 +110,8 @@ export const fixFloat = (num: number): number => { return parseFloat(num.toFixed(getDecimalPlaces(num))) } +export const sleep = async (ms: number): Promise => { + await new Promise((resolve) => setTimeout(resolve, ms)) +} + export { toHex } From f83b7a7de390b670316e1dad5a35ad323d96a25f Mon Sep 17 00:00:00 2001 From: Halil Beycan <50718965+BeycanDeveloper@users.noreply.github.com> Date: Tue, 26 Mar 2024 18:56:07 +0800 Subject: [PATCH 021/114] completed token asset --- packages/networks/evm-chains/package.json | 4 +-- packages/networks/evm-chains/pnpm-lock.yaml | 16 ++++++------ .../networks/evm-chains/src/assets/Coin.ts | 14 ++++++----- .../evm-chains/src/assets/Contract.ts | 3 +-- .../networks/evm-chains/src/assets/Token.ts | 5 ++-- .../evm-chains/src/models/Transaction.ts | 25 +++++++++++++------ .../networks/evm-chains/tests/assets.spec.ts | 13 +++++----- packages/networks/evm-chains/tests/setup.ts | 4 +-- 8 files changed, 48 insertions(+), 36 deletions(-) diff --git a/packages/networks/evm-chains/package.json b/packages/networks/evm-chains/package.json index 1e91902..71fd06f 100644 --- a/packages/networks/evm-chains/package.json +++ b/packages/networks/evm-chains/package.json @@ -38,7 +38,7 @@ "url": "https://github.com/MultipleChain/js/issues" }, "dependencies": { - "@multiplechain/types": "^0.1.18", - "@multiplechain/utils": "^0.1.8" + "@multiplechain/types": "^0.1.19", + "@multiplechain/utils": "^0.1.9" } } \ No newline at end of file diff --git a/packages/networks/evm-chains/pnpm-lock.yaml b/packages/networks/evm-chains/pnpm-lock.yaml index f9666d7..2d3be73 100644 --- a/packages/networks/evm-chains/pnpm-lock.yaml +++ b/packages/networks/evm-chains/pnpm-lock.yaml @@ -6,20 +6,20 @@ settings: dependencies: '@multiplechain/types': - specifier: ^0.1.18 - version: 0.1.18 + specifier: ^0.1.19 + version: 0.1.19 '@multiplechain/utils': - specifier: ^0.1.8 - version: 0.1.8 + specifier: ^0.1.9 + version: 0.1.9 packages: - /@multiplechain/types@0.1.18: - resolution: {integrity: sha512-HToqt7TUG5BCQzoHT1NOS69KG/CS+JWFi4+VF/4xf4v8dmbHSybNnN8727Nnn6oGPv9g6fKcAvR4306xxZkSJg==} + /@multiplechain/types@0.1.19: + resolution: {integrity: sha512-mW3aAMuplEPOUFJiAf5vLXW/vnRxcBReFeu6Lo6rDmcNxujpDz1sJG1qhiRsiJL2Wynjls0mpIfAMtImO+0SDg==} dev: false - /@multiplechain/utils@0.1.8: - resolution: {integrity: sha512-AJxrAiHm+hoTOgeCFL6rXHV/EeDpmXe9KLtwNOQx8Pnqbz1sIiHEedhSGohkQsJddq8/e1d0MCBGqi7GFmtqSw==} + /@multiplechain/utils@0.1.9: + resolution: {integrity: sha512-52yrmloGDwXrMwOSfEiPJfePPIDeEqGMTE4u5QE2BQPdGe0Bto908pX4IIF1j0Srmv5TJdH9JN3MFEgzgo3qAw==} dependencies: bignumber.js: 9.1.2 web3-utils: 4.2.0 diff --git a/packages/networks/evm-chains/src/assets/Coin.ts b/packages/networks/evm-chains/src/assets/Coin.ts index 1085341..838a36f 100644 --- a/packages/networks/evm-chains/src/assets/Coin.ts +++ b/packages/networks/evm-chains/src/assets/Coin.ts @@ -4,28 +4,29 @@ import { TransactionSigner } from '../services/TransactionSigner.ts' import type { TransactionData } from '../services/TransactionSigner.ts' import type { CoinInterface } from '@multiplechain/types' -const { network, ethers } = Provider.instance - export class Coin implements CoinInterface { /** * @returns Coin name */ getName(): string { - return network.nativeCurrency.name ?? network.nativeCurrency.symbol + return ( + Provider.instance.network.nativeCurrency.name ?? + Provider.instance.network.nativeCurrency.symbol + ) } /** * @returns Coin symbol */ getSymbol(): string { - return network.nativeCurrency.symbol + return Provider.instance.network.nativeCurrency.symbol } /** * @returns Decimal value of the coin */ getDecimals(): number { - return network.nativeCurrency.decimals + return Provider.instance.network.nativeCurrency.decimals } /** @@ -33,7 +34,7 @@ export class Coin implements CoinInterface { * @returns Wallet balance as currency of TOKEN or COIN assets */ async getBalance(owner: string): Promise { - const balance = await ethers.getBalance(owner) + const balance = await Provider.instance.ethers.getBalance(owner) return hexToNumber(balance.toString(), this.getDecimals()) } @@ -51,6 +52,7 @@ export class Coin implements CoinInterface { throw new Error('Insufficient balance') } + const { network, ethers } = Provider.instance const hexAmount = numberToHex(amount, this.getDecimals()) const txData: TransactionData = { diff --git a/packages/networks/evm-chains/src/assets/Contract.ts b/packages/networks/evm-chains/src/assets/Contract.ts index 46627b4..ab750c1 100644 --- a/packages/networks/evm-chains/src/assets/Contract.ts +++ b/packages/networks/evm-chains/src/assets/Contract.ts @@ -2,8 +2,6 @@ import type { ContractInterface } from '@multiplechain/types' import type { Contract as EthersContract } from 'ethers' import { Provider } from '../services/Provider.ts' -const { ethers } = Provider.instance - export class Contract implements ContractInterface { /** * Contract address @@ -27,6 +25,7 @@ export class Contract implements ContractInterface { constructor(address: string, abi: object[]) { this.abi = abi this.address = address + const { ethers } = Provider.instance this.ethersContract = ethers.contract(address, abi, ethers.jsonRpc) } diff --git a/packages/networks/evm-chains/src/assets/Token.ts b/packages/networks/evm-chains/src/assets/Token.ts index 260a322..5ba94eb 100644 --- a/packages/networks/evm-chains/src/assets/Token.ts +++ b/packages/networks/evm-chains/src/assets/Token.ts @@ -5,8 +5,6 @@ import { TransactionSigner } from '../services/TransactionSigner.ts' import { hexToNumber, numberToHex } from '@multiplechain/utils' import type { TokenInterface } from '@multiplechain/types' -const { network, ethers } = Provider.instance - export class Token extends Contract implements TokenInterface { constructor(address: string) { super(address, ERC20) @@ -69,6 +67,8 @@ export class Token extends Contract implements TokenInterface { throw new Error('Insufficient balance') } + const { network, ethers } = Provider.instance + const hexAmount = numberToHex(amount, decimals) const [gasPrice, nonce, data, gasLimit] = await Promise.all([ ethers.getGasPrice(), @@ -106,6 +106,7 @@ export class Token extends Contract implements TokenInterface { throw new Error('Insufficient balance') } + const { network, ethers } = Provider.instance const hexAmount = numberToHex(amount, decimals) const [gasPrice, nonce, data, gasLimit] = await Promise.all([ diff --git a/packages/networks/evm-chains/src/models/Transaction.ts b/packages/networks/evm-chains/src/models/Transaction.ts index 8d60884..e6a7d3a 100644 --- a/packages/networks/evm-chains/src/models/Transaction.ts +++ b/packages/networks/evm-chains/src/models/Transaction.ts @@ -2,8 +2,7 @@ import { Provider } from '../services/Provider.ts' import { TransactionStatusEnum } from '@multiplechain/types' import type { TransactionInterface } from '@multiplechain/types' import type { TransactionReceipt, TransactionResponse } from 'ethers' - -const { ethers } = Provider.instance +import type { Ethers } from '../services/Ethers.ts' interface TransactionData { response: TransactionResponse @@ -16,8 +15,14 @@ export class Transaction implements TransactionInterface { */ id: string + /** + * Ethers service + */ + ethers: Ethers + constructor(id: string) { this.id = id + this.ethers = Provider.instance.ethers } /** @@ -25,9 +30,12 @@ export class Transaction implements TransactionInterface { */ async getData(): Promise { try { - const response = await ethers.getTransaction(this.id) - const receipt = await ethers.getTransactionReceipt(this.id) - if (response === null || receipt === null) { + const response = await this.ethers.getTransaction(this.id) + if (response === null) { + return null + } + const receipt = await this.ethers.getTransactionReceipt(this.id) + if (receipt === null) { return null } return { response, receipt } @@ -40,18 +48,19 @@ export class Transaction implements TransactionInterface { } } - async wait(): Promise { + async wait(ms: number = 4000): Promise { return await new Promise((resolve, reject) => { const check = async (): Promise => { try { const status = await this.getStatus() - console.log(status) if (status === TransactionStatusEnum.CONFIRMED) { resolve(TransactionStatusEnum.CONFIRMED) + return } else if (status === TransactionStatusEnum.FAILED) { reject(TransactionStatusEnum.FAILED) + return } - setTimeout(check, 4000) + setTimeout(check, ms) } catch (error) { reject(TransactionStatusEnum.FAILED) } diff --git a/packages/networks/evm-chains/tests/assets.spec.ts b/packages/networks/evm-chains/tests/assets.spec.ts index 1ff2aaf..644c20d 100644 --- a/packages/networks/evm-chains/tests/assets.spec.ts +++ b/packages/networks/evm-chains/tests/assets.spec.ts @@ -3,13 +3,13 @@ import { describe, it, expect, assert } from 'vitest' import ERC20 from '../resources/erc20.json' import { Coin } from '../src/assets/Coin.ts' import { Token } from '../src/assets/Token.ts' -import { numberToHex } from '@multiplechain/utils' +import { numberToHex, fixFloat } from '@multiplechain/utils' import { Contract } from '../src/assets/Contract.ts' import { Transaction } from '../src/models/Transaction.ts' import { TransactionStatusEnum } from '@multiplechain/types' import { TransactionSigner } from '../src/services/TransactionSigner.ts' -const transferTestIsOpen = true +const transferTestIsOpen = false const balanceTestAddress = '0x760A4d3D03928D1e8541A7644B34370c1b79aa9F' const coinBalanceTestAmount = 0.01 @@ -37,8 +37,8 @@ const checkSigner = async (signer: TransactionSigner): Promise => { const checkTx = async (transaction: Transaction): Promise => { expect(transaction).toBeInstanceOf(Transaction) - await transaction.wait() - expect(await transaction.getStatus()).toBe(TransactionStatusEnum.CONFIRMED) + const status = await transaction.wait() + expect(status).toBe(TransactionStatusEnum.CONFIRMED) } describe('Coin', () => { @@ -72,7 +72,7 @@ describe('Coin', () => { await checkTx(await signer.send()) const afterBalance = await coin.getBalance(receiverTestAddress) - expect(afterBalance).toBe(beforeBalance + transferTestAmount) + expect(afterBalance).toBe(fixFloat(beforeBalance + transferTestAmount)) }) }) @@ -130,10 +130,11 @@ describe('Token', () => { await checkTx(await signer.send()) const afterBalance = await token.getBalance(receiverTestAddress) - expect(afterBalance).toBe(beforeBalance + transferTestAmount) + expect(afterBalance).toBe(fixFloat(beforeBalance + tokenTransferTestAmount)) }) it('Approve and Allowance', async () => { + if (!transferTestIsOpen) return const signer = await token.approve( senderTestAddress, receiverTestAddress, diff --git a/packages/networks/evm-chains/tests/setup.ts b/packages/networks/evm-chains/tests/setup.ts index 3aa18e1..74c5dc0 100644 --- a/packages/networks/evm-chains/tests/setup.ts +++ b/packages/networks/evm-chains/tests/setup.ts @@ -5,8 +5,8 @@ export const provider = new Provider({ hexId: '0xaa36a7', mainnetId: 1, name: 'Ethereum Sepolia Testnet (QR)', - rpcUrl: 'https://sepolia.infura.io/v3/9aa3d95b3bc440fa88ea12eaa4456161', - wsUrl: 'wss://sepolia.infura.io/ws/v3/9aa3d95b3bc440fa88ea12eaa4456161', + rpcUrl: 'https://dimensional-icy-tent.ethereum-sepolia.quiknode.pro/e6a31d965b3ab5fc57d5980d187121f1894c0eb4/', + wsUrl: 'wss://dimensional-icy-tent.ethereum-sepolia.quiknode.pro/e6a31d965b3ab5fc57d5980d187121f1894c0eb4/', explorerUrl: 'https://sepolia.etherscan.io/', nativeCurrency: { symbol: 'ETH', From b9639f2bc8a196a62b5fce825e4695a35a3b2427 Mon Sep 17 00:00:00 2001 From: Halil Beycan <50718965+BeycanDeveloper@users.noreply.github.com> Date: Tue, 26 Mar 2024 18:56:26 +0800 Subject: [PATCH 022/114] updated --- packages/networks/boilerplate/package.json | 2 +- vitest.config.ts | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/networks/boilerplate/package.json b/packages/networks/boilerplate/package.json index ff7c1de..c60b737 100644 --- a/packages/networks/boilerplate/package.json +++ b/packages/networks/boilerplate/package.json @@ -36,7 +36,7 @@ "url": "https://github.com/MultipleChain/js/issues" }, "dependencies": { - "@multiplechain/types": "^0.1.18", + "@multiplechain/types": "^0.1.19", "@multiplechain/utils": "^0.1.8" } } \ No newline at end of file diff --git a/vitest.config.ts b/vitest.config.ts index 791dee3..817263e 100644 --- a/vitest.config.ts +++ b/vitest.config.ts @@ -6,6 +6,7 @@ export default mergeConfig( viteConfig, defineConfig({ test: { + testTimeout: 180000, environment: 'jsdom', exclude: [...configDefaults.exclude, 'e2e/*'], root: fileURLToPath(new URL('./', import.meta.url)), From b9ad78be147964b40ee5d2a51c21eb4c53acfbe0 Mon Sep 17 00:00:00 2001 From: Halil Beycan <50718965+BeycanDeveloper@users.noreply.github.com> Date: Tue, 26 Mar 2024 19:32:21 +0800 Subject: [PATCH 023/114] added new method types for token and nft --- packages/types/package.json | 2 +- packages/types/src/assets.ts | 39 +++++++++++++++++++++++++++++++++++- 2 files changed, 39 insertions(+), 2 deletions(-) diff --git a/packages/types/package.json b/packages/types/package.json index 31d93c6..7946c9b 100644 --- a/packages/types/package.json +++ b/packages/types/package.json @@ -1,6 +1,6 @@ { "name": "@multiplechain/types", - "version": "0.1.19", + "version": "0.1.20", "type": "module", "main": "./src/index.ts", "types": "./src/index.ts", diff --git a/packages/types/src/assets.ts b/packages/types/src/assets.ts index b0e8b63..3f08ec2 100644 --- a/packages/types/src/assets.ts +++ b/packages/types/src/assets.ts @@ -94,10 +94,22 @@ export interface TokenInterface */ getTotalSupply: () => Promise + /** + * @param owner Sender wallet address + * @param receiver Receiver wallet address + * @param amount Amount of tokens that will be transferred + * @override transfer() in AssetInterface + */ + transferFrom: ( + owner: string, + receiver: string, + amount: number + ) => Promise + /** * Gives permission to the spender to spend owner's tokens * @param owner Address of owner of the tokens that will be used - * @param spender Address of the spender that will use the tokens of owner + * @param spender Address of the spender that is using the tokens of owner * @param amount Amount of the tokens that will be used */ approve: (owner: string, spender: string, amount: number) => Promise @@ -147,4 +159,29 @@ export interface NftInterface receiver: string, nftId: number ) => Promise + + /** + * @param owner Address of owner of the nfts that will be used + * @param receiver Address of the receiver that will receive the nfts + * @param nftId ID of the NFT that will be transferred + */ + transferFrom: ( + owner: string, + receiver: string, + nftId: number + ) => Promise + + /** + * Gives permission to the spender to spend owner's tokens + * @param owner Address of owner of the tokens that will be used + * @param spender Address of the spender that will use the tokens of owner + * @param nftId ID of the NFT that will be transferred + */ + approve: (owner: string, spender: string, nftId: number) => Promise + + /** + * @param nftId ID of the NFT that will be transferred + * @returns Amount of the tokens that is being used by spender + */ + getApproved: (nftId: number) => Promise } From 349fd91c18bc5d9917b91f171388d9e9fb77e69b Mon Sep 17 00:00:00 2001 From: Halil Beycan <50718965+BeycanDeveloper@users.noreply.github.com> Date: Tue, 26 Mar 2024 19:33:25 +0800 Subject: [PATCH 024/114] updated --- packages/networks/boilerplate/package.json | 2 +- packages/networks/evm-chains/package.json | 2 +- packages/networks/evm-chains/pnpm-lock.yaml | 8 ++++---- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/networks/boilerplate/package.json b/packages/networks/boilerplate/package.json index c60b737..3ea7780 100644 --- a/packages/networks/boilerplate/package.json +++ b/packages/networks/boilerplate/package.json @@ -36,7 +36,7 @@ "url": "https://github.com/MultipleChain/js/issues" }, "dependencies": { - "@multiplechain/types": "^0.1.19", + "@multiplechain/types": "^0.1.20", "@multiplechain/utils": "^0.1.8" } } \ No newline at end of file diff --git a/packages/networks/evm-chains/package.json b/packages/networks/evm-chains/package.json index 71fd06f..f810112 100644 --- a/packages/networks/evm-chains/package.json +++ b/packages/networks/evm-chains/package.json @@ -38,7 +38,7 @@ "url": "https://github.com/MultipleChain/js/issues" }, "dependencies": { - "@multiplechain/types": "^0.1.19", + "@multiplechain/types": "^0.1.20", "@multiplechain/utils": "^0.1.9" } } \ No newline at end of file diff --git a/packages/networks/evm-chains/pnpm-lock.yaml b/packages/networks/evm-chains/pnpm-lock.yaml index 2d3be73..4095190 100644 --- a/packages/networks/evm-chains/pnpm-lock.yaml +++ b/packages/networks/evm-chains/pnpm-lock.yaml @@ -6,16 +6,16 @@ settings: dependencies: '@multiplechain/types': - specifier: ^0.1.19 - version: 0.1.19 + specifier: ^0.1.20 + version: 0.1.20 '@multiplechain/utils': specifier: ^0.1.9 version: 0.1.9 packages: - /@multiplechain/types@0.1.19: - resolution: {integrity: sha512-mW3aAMuplEPOUFJiAf5vLXW/vnRxcBReFeu6Lo6rDmcNxujpDz1sJG1qhiRsiJL2Wynjls0mpIfAMtImO+0SDg==} + /@multiplechain/types@0.1.20: + resolution: {integrity: sha512-2pHnnQEhJYy27v7ZPDMRjdLJrXBFRx05+5KXD3oxJozoWD9vTLfE6dWHdqL+4/4vQSXGi+8tEQsCRHWFRuLllw==} dev: false /@multiplechain/utils@0.1.9: From 87ca8e8916737324bbadf5883903c8e0d62d6412 Mon Sep 17 00:00:00 2001 From: Halil Beycan <50718965+BeycanDeveloper@users.noreply.github.com> Date: Tue, 26 Mar 2024 19:46:28 +0800 Subject: [PATCH 025/114] updated transferFrom types --- packages/types/package.json | 2 +- packages/types/src/assets.ts | 4 ++++ packages/types/src/enums.ts | 1 + 3 files changed, 6 insertions(+), 1 deletion(-) diff --git a/packages/types/package.json b/packages/types/package.json index 7946c9b..b61c1f7 100644 --- a/packages/types/package.json +++ b/packages/types/package.json @@ -1,6 +1,6 @@ { "name": "@multiplechain/types", - "version": "0.1.20", + "version": "0.1.21", "type": "module", "main": "./src/index.ts", "types": "./src/index.ts", diff --git a/packages/types/src/assets.ts b/packages/types/src/assets.ts index 3f08ec2..6e2a449 100644 --- a/packages/types/src/assets.ts +++ b/packages/types/src/assets.ts @@ -95,12 +95,14 @@ export interface TokenInterface getTotalSupply: () => Promise /** + * @param spender Address of the spender of transaction * @param owner Sender wallet address * @param receiver Receiver wallet address * @param amount Amount of tokens that will be transferred * @override transfer() in AssetInterface */ transferFrom: ( + spender: string, owner: string, receiver: string, amount: number @@ -161,11 +163,13 @@ export interface NftInterface ) => Promise /** + * @param spender Address of the spender of transaction * @param owner Address of owner of the nfts that will be used * @param receiver Address of the receiver that will receive the nfts * @param nftId ID of the NFT that will be transferred */ transferFrom: ( + spender: string, owner: string, receiver: string, nftId: number diff --git a/packages/types/src/enums.ts b/packages/types/src/enums.ts index ea1d409..444f739 100644 --- a/packages/types/src/enums.ts +++ b/packages/types/src/enums.ts @@ -36,6 +36,7 @@ export enum ErrorTypeEnum { RPC_REQUEST_ERROR = 'RPC_REQUEST_ERROR', RPC_ACCESS_DENIED = 'RPC_ACCESS_DENIED', UNACCEPTED_CHAIN = 'UNACCEPTED_CHAIN', + UNAUTHORIZED_ADDRESS = 'UNAUTHORIZED_ADDRESS', INSUFFICIENT_BALANCE = 'INSUFFICIENT_BALANCE', INVALID_AMOUNT = 'INVALID_AMOUNT', INVALID_ADDRESS = 'INVALID_ADDRESS', From 5fc88aadebd2c83c58fcf5bb9721d68c5bfdce1e Mon Sep 17 00:00:00 2001 From: Halil Beycan <50718965+BeycanDeveloper@users.noreply.github.com> Date: Tue, 26 Mar 2024 19:47:03 +0800 Subject: [PATCH 026/114] updated --- packages/networks/boilerplate/package.json | 2 +- packages/networks/evm-chains/package.json | 2 +- packages/networks/evm-chains/pnpm-lock.yaml | 8 ++++---- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/networks/boilerplate/package.json b/packages/networks/boilerplate/package.json index 3ea7780..5e81567 100644 --- a/packages/networks/boilerplate/package.json +++ b/packages/networks/boilerplate/package.json @@ -36,7 +36,7 @@ "url": "https://github.com/MultipleChain/js/issues" }, "dependencies": { - "@multiplechain/types": "^0.1.20", + "@multiplechain/types": "^0.1.21", "@multiplechain/utils": "^0.1.8" } } \ No newline at end of file diff --git a/packages/networks/evm-chains/package.json b/packages/networks/evm-chains/package.json index f810112..c6f23db 100644 --- a/packages/networks/evm-chains/package.json +++ b/packages/networks/evm-chains/package.json @@ -38,7 +38,7 @@ "url": "https://github.com/MultipleChain/js/issues" }, "dependencies": { - "@multiplechain/types": "^0.1.20", + "@multiplechain/types": "^0.1.21", "@multiplechain/utils": "^0.1.9" } } \ No newline at end of file diff --git a/packages/networks/evm-chains/pnpm-lock.yaml b/packages/networks/evm-chains/pnpm-lock.yaml index 4095190..62e8f1b 100644 --- a/packages/networks/evm-chains/pnpm-lock.yaml +++ b/packages/networks/evm-chains/pnpm-lock.yaml @@ -6,16 +6,16 @@ settings: dependencies: '@multiplechain/types': - specifier: ^0.1.20 - version: 0.1.20 + specifier: ^0.1.21 + version: 0.1.21 '@multiplechain/utils': specifier: ^0.1.9 version: 0.1.9 packages: - /@multiplechain/types@0.1.20: - resolution: {integrity: sha512-2pHnnQEhJYy27v7ZPDMRjdLJrXBFRx05+5KXD3oxJozoWD9vTLfE6dWHdqL+4/4vQSXGi+8tEQsCRHWFRuLllw==} + /@multiplechain/types@0.1.21: + resolution: {integrity: sha512-x42yGCAGUEFPdhbyMw3tyZ9eAWztR8EIWdg7JkVedfnWZ4E0y6hIcr+HMInP2zJpQZIh+w73k94bJyoHklOjFg==} dev: false /@multiplechain/utils@0.1.9: From 37bbbb4d5a826b383d3790c305f5e454f4b9aa2e Mon Sep 17 00:00:00 2001 From: Halil Beycan <50718965+BeycanDeveloper@users.noreply.github.com> Date: Tue, 26 Mar 2024 21:30:31 +0800 Subject: [PATCH 027/114] updated getStatus method --- packages/networks/evm-chains/src/models/Transaction.ts | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/packages/networks/evm-chains/src/models/Transaction.ts b/packages/networks/evm-chains/src/models/Transaction.ts index e6a7d3a..201437a 100644 --- a/packages/networks/evm-chains/src/models/Transaction.ts +++ b/packages/networks/evm-chains/src/models/Transaction.ts @@ -124,10 +124,8 @@ export class Transaction implements TransactionInterface { */ async getStatus(): Promise { const data = await this.getData() - if (data === null) { - return TransactionStatusEnum.PENDING - } else if (data.response.blockNumber !== null) { - if (data.receipt.status === 1) { + if (data?.response?.blockNumber !== null) { + if (data?.receipt.status === 1) { return TransactionStatusEnum.CONFIRMED } else { return TransactionStatusEnum.FAILED From 8444f733359c8f63415cb56ef0d25e79c856556f Mon Sep 17 00:00:00 2001 From: oynozan Date: Wed, 27 Mar 2024 14:39:30 +0300 Subject: [PATCH 028/114] transaction signer types + NFT asset --- .../networks/evm-chains/src/assets/Coin.ts | 0 .../evm-chains/src/assets/Contract.ts | 0 .../networks/evm-chains/src/assets/NFT.ts | 147 +++++++++++++---- .../networks/evm-chains/src/assets/Token.ts | 28 +++- .../src/services/TransactionListener.ts | 149 ++++++++++-------- .../src/services/TransactionSigner.ts | 112 ++++++++----- packages/types/src/enums.ts | 1 - 7 files changed, 297 insertions(+), 140 deletions(-) mode change 100644 => 100755 packages/networks/evm-chains/src/assets/Coin.ts mode change 100644 => 100755 packages/networks/evm-chains/src/assets/Contract.ts mode change 100644 => 100755 packages/networks/evm-chains/src/assets/NFT.ts mode change 100644 => 100755 packages/networks/evm-chains/src/assets/Token.ts mode change 100644 => 100755 packages/networks/evm-chains/src/services/TransactionListener.ts mode change 100644 => 100755 packages/networks/evm-chains/src/services/TransactionSigner.ts mode change 100644 => 100755 packages/types/src/enums.ts diff --git a/packages/networks/evm-chains/src/assets/Coin.ts b/packages/networks/evm-chains/src/assets/Coin.ts old mode 100644 new mode 100755 diff --git a/packages/networks/evm-chains/src/assets/Contract.ts b/packages/networks/evm-chains/src/assets/Contract.ts old mode 100644 new mode 100755 diff --git a/packages/networks/evm-chains/src/assets/NFT.ts b/packages/networks/evm-chains/src/assets/NFT.ts old mode 100644 new mode 100755 index 4d7ebfc..5ec6704 --- a/packages/networks/evm-chains/src/assets/NFT.ts +++ b/packages/networks/evm-chains/src/assets/NFT.ts @@ -1,68 +1,161 @@ import { Contract } from './Contract.ts' import ERC721 from '../../resources/erc721.json' +import { Provider } from '../services/Provider.ts' import { TransactionSigner } from '../services/TransactionSigner.ts' -import type { NftInterface, TransactionSignerInterface } from '@multiplechain/types' +import { ErrorTypeEnum, type NftInterface } from '@multiplechain/types' export class NFT extends Contract implements NftInterface { + constructor(address: string) { + super(address, ERC721) + } + /** * @returns Contract name */ - getName(): string { - return 'example' + async getName(): Promise { + return await this.callMethod('name') } /** * @returns Contract symbol */ - getSymbol(): string { - return 'example' + async getSymbol(): Promise { + return await this.callMethod('symbol') } /** * @param owner Wallet address - * @returns Wallet balance as currency of TOKEN or COIN assets + * @returns Number of tokens of owner */ - getBalance(owner: string): number { - return 0 + async getBalance(owner: string): Promise { + return await this.ethersContract.balanceOf(owner) } /** - * @returns Contract address + * @param sender Sender address + * @param receiver Receiver address + * @param nftId NFT ID + * @returns Transaction signer */ - getAddress(): string { - return 'example' + async transfer(sender: string, receiver: string, nftId: number): Promise { + // Check if tokens exist + const balance = await this.getBalance(sender) + + if (balance <= 0) { + throw new Error(ErrorTypeEnum.INSUFFICIENT_BALANCE) + } + + // Check ownership + const originalOwner = await this.getOwner(nftId) + if (originalOwner !== sender) { + throw new Error(ErrorTypeEnum.UNAUTHORIZED_ADDRESS) + } + + const { network, ethers } = Provider.instance + + const [gasPrice, nonce, data, gasLimit] = await Promise.all([ + ethers.getGasPrice(), + ethers.getNonce(sender), + this.getMethodData('transfer', receiver, nftId), + this.getMethodEstimateGas('transfer', sender, receiver, nftId) + ]) + + return new TransactionSigner({ + data, + nonce, + gasPrice, + gasLimit, + value: '0x0', + from: sender, + chainId: network.id, + to: receiver + }) + } + + async transferFrom( + spender: string, + owner: string, + receiver: string, + nftId: number + ): Promise { + // Check if tokens exist + const balance = await this.getBalance(owner) + + if (balance <= 0) { + throw new Error(ErrorTypeEnum.INSUFFICIENT_BALANCE) + } + + // Check ownership + const originalOwner = await this.getOwner(nftId) + if (originalOwner !== owner) { + throw new Error(ErrorTypeEnum.UNAUTHORIZED_ADDRESS) + } + + // } /** - * @returns NFT ID + * @param nftId NFT ID + * @returns NFT owner wallet address */ - getNftId(): number { - return 0 + async getOwner(nftId: number): Promise { + return await this.ethersContract.ownerOf(nftId) } /** - * @param sender Sender address - * @param receiver Receiver address * @param nftId NFT ID - * @returns Transaction signer + * @returns NFT URI */ - transfer(sender: string, receiver: string, nftId: number): TransactionSignerInterface { - return new TransactionSigner('example') + async getTokenURI(nftId: number): Promise { + return await this.ethersContract.tokenURI(nftId) } /** - * @param nftId NFT ID - * @returns NFT owner wallet address + * Gives permission to the spender to spend owner's tokens + * @param owner Address of owner of the tokens that will be used + * @param spender Address of the spender that will use the tokens of owner + * @param nftId ID of the NFT that will be transferred */ - getOwner(nftId: number): string { - return 'example' + async approve(owner: string, spender: string, nftId: number): Promise { + // Check if tokens exist + const balance = await this.getBalance(owner) + + if (balance <= 0) { + throw new Error(ErrorTypeEnum.INSUFFICIENT_BALANCE) + } + + // Check ownership + const originalOwner = await this.getOwner(nftId) + if (originalOwner !== owner) { + throw new Error(ErrorTypeEnum.UNAUTHORIZED_ADDRESS) + } + + const { network, ethers } = Provider.instance + + const [gasPrice, nonce, data, gasLimit] = await Promise.all([ + ethers.getGasPrice(), + ethers.getNonce(owner), + this.getMethodData('approve', spender, nftId), + this.getMethodEstimateGas('approve', owner, spender, nftId) + ]) + + return new TransactionSigner({ + data, + nonce, + gasPrice, + gasLimit, + value: '0x0', + from: owner, + chainId: network.id, + to: spender + }) } /** - * @param nftId NFT ID - * @returns NFT URI + * @param nftId ID of the NFT that will be transferred + * @returns Amount of the tokens that is being used by spender */ - getTokenURI(nftId: number): string { - return 'example' + async getApproved(nftId: number): Promise { + return await this.ethersContract.getApproved(nftId) } } diff --git a/packages/networks/evm-chains/src/assets/Token.ts b/packages/networks/evm-chains/src/assets/Token.ts old mode 100644 new mode 100755 index 5ba94eb..d1750c7 --- a/packages/networks/evm-chains/src/assets/Token.ts +++ b/packages/networks/evm-chains/src/assets/Token.ts @@ -1,9 +1,10 @@ +import { hexToNumber, numberToHex } from '@multiplechain/utils' +import { ErrorTypeEnum, type TokenInterface } from '@multiplechain/types' + import { Contract } from './Contract.ts' import ERC20 from '../../resources/erc20.json' import { Provider } from '../services/Provider.ts' import { TransactionSigner } from '../services/TransactionSigner.ts' -import { hexToNumber, numberToHex } from '@multiplechain/utils' -import type { TokenInterface } from '@multiplechain/types' export class Token extends Contract implements TokenInterface { constructor(address: string) { @@ -89,6 +90,25 @@ export class Token extends Contract implements TokenInterface { }) } + /** + * transferFrom() transfers tokens from sender to receiver using allowance + * @param sender Sender wallet address + * @param receiver Receiver wallet address + * @param amount Amount of assets that will be transferred + */ + async transferFrom( + spender: string, + owner: string, + receiver: string, + amount: number + ): Promise { + if (amount < 0) { + throw new Error(ErrorTypeEnum.INVALID_AMOUNT) + } + + // + } + /** * Gives permission to the spender to spend owner's tokens * @param owner Address of owner of the tokens that will be used @@ -97,13 +117,13 @@ export class Token extends Contract implements TokenInterface { */ async approve(owner: string, spender: string, amount: number): Promise { if (amount < 0) { - throw new Error('Invalid amount') + throw new Error(ErrorTypeEnum.INVALID_AMOUNT) } const [balance, decimals] = await Promise.all([this.getBalance(owner), this.getDecimals()]) if (amount > balance) { - throw new Error('Insufficient balance') + throw new Error(ErrorTypeEnum.INSUFFICIENT_BALANCE) } const { network, ethers } = Provider.instance diff --git a/packages/networks/evm-chains/src/services/TransactionListener.ts b/packages/networks/evm-chains/src/services/TransactionListener.ts old mode 100644 new mode 100755 index 5382093..985269d --- a/packages/networks/evm-chains/src/services/TransactionListener.ts +++ b/packages/networks/evm-chains/src/services/TransactionListener.ts @@ -1,106 +1,115 @@ -import type { - TransactionTypeEnum, - DynamicTransactionType, - TransactionListenerInterface, - TransactionListenerCallbackType, - DynamicTransactionListenerFilterType -} from '@multiplechain/types' - -import { TransactionListenerProcessIndex } from '@multiplechain/types' - -export class TransactionListener - implements TransactionListenerInterface -{ - /** - * Transaction type - */ - type: T +import { Provider } from '../services/Provider.ts' +import type { TransactionRequest, Wallet, BigNumberish } from 'ethers' +import { TransactionTypeEnum, type TransactionSignerInterface } from '@multiplechain/types' - /** - * Transaction listener callback - */ - callbacks: TransactionListenerCallbackType[] = [] +// Transactions +import { Transaction } from '../models/Transaction.ts' +import { NftTransaction } from '../models/NftTransaction.ts' +import { CoinTransaction } from '../models/CoinTransaction.ts' +import { TokenTransaction } from '../models/TokenTransaction.ts' +import { ContractTransaction } from '../models/ContractTransaction.ts' - /** - * Transaction listener filter - */ - filter: DynamicTransactionListenerFilterType +export interface TransactionData extends TransactionRequest { + gas?: BigNumberish +} - /** - * @param type - Transaction type - * @param filter - Transaction listener filter - */ - constructor(type: T, filter: DynamicTransactionListenerFilterType) { - this.type = type - this.filter = filter - // @ts-expect-error allow dynamic access - this[TransactionListenerProcessIndex[type]]() - } +const { ethers } = Provider.instance +export class TransactionSigner implements TransactionSignerInterface { /** - * Close the listener + * Transaction data from the blockchain network */ - stop(): void { - // Close the listener - } + rawData: TransactionData /** - * Listen to the transaction events - * @param callback - Callback function + * Transaction type */ - on(callback: TransactionListenerCallbackType): void { - this.callbacks.push(callback) - } + type: TransactionTypeEnum /** - * Trigger the event when a transaction is detected - * @param transaction - Transaction data + * Signed transaction data */ - trigger(transaction: DynamicTransactionType): void { - this.callbacks.forEach((callback) => { - callback(transaction) - }) - } + signedData: string /** - * General transaction process + * Wallet instance from ethers with the private key */ - generalProcess(): void { - // General transaction process - } + wallet: Wallet /** - * Contract transaction process + * @param rawData - Transaction data */ - contractProcess(): void { - // Contract transaction process + constructor(rawData: TransactionData, type?: TransactionTypeEnum) { + this.rawData = rawData + if (type !== undefined) this.type = type } /** - * Asset transaction process + * Sign the transaction + * @param privateKey - Transaction data */ - assetProcess(): void { - // Asset transaction process + public async sign(privateKey: string): Promise { + this.wallet = ethers.wallet(privateKey) + this.signedData = await this.wallet.signTransaction(this.rawData) + return this } /** - * Coin transaction process + * Send the transaction to the blockchain network + * @returns Promise of the transaction */ - coinProcess(): void { - // Coin transaction process + async send(): Promise { + switch (this.type) { + case TransactionTypeEnum.COIN: + return new CoinTransaction( + (await ethers.jsonRpc.send('eth_sendRawTransaction', [ + this.signedData + ])) as string + ) + + case TransactionTypeEnum.TOKEN: + return new TokenTransaction( + (await ethers.jsonRpc.send('eth_sendRawTransaction', [ + this.signedData + ])) as string + ) + + case TransactionTypeEnum.NFT: + return new NftTransaction( + (await ethers.jsonRpc.send('eth_sendRawTransaction', [ + this.signedData + ])) as string + ) + + case TransactionTypeEnum.CONTRACT: + return new ContractTransaction( + (await ethers.jsonRpc.send('eth_sendRawTransaction', [ + this.signedData + ])) as string + ) + + default: + return new Transaction( + (await ethers.jsonRpc.send('eth_sendRawTransaction', [ + this.signedData + ])) as string + ) + } } /** - * Token transaction process + * Get the raw transaction data + * @returns Transaction data */ - tokenProcess(): void { - // Token transaction process + getRawData(): any { + return this.rawData } /** - * NFT transaction process + * Get the signed transaction data + * @returns Signed transaction data */ - nftProcess(): void { - // NFT transaction process + getSignedData(): any { + return this.signedData } } diff --git a/packages/networks/evm-chains/src/services/TransactionSigner.ts b/packages/networks/evm-chains/src/services/TransactionSigner.ts old mode 100644 new mode 100755 index 0ae63df..5382093 --- a/packages/networks/evm-chains/src/services/TransactionSigner.ts +++ b/packages/networks/evm-chains/src/services/TransactionSigner.ts @@ -1,70 +1,106 @@ -import { Provider } from '../services/Provider.ts' -import { Transaction } from '../models/Transaction.ts' -import type { TransactionRequest, Wallet, BigNumberish } from 'ethers' -import type { TransactionSignerInterface } from '@multiplechain/types' +import type { + TransactionTypeEnum, + DynamicTransactionType, + TransactionListenerInterface, + TransactionListenerCallbackType, + DynamicTransactionListenerFilterType +} from '@multiplechain/types' -export interface TransactionData extends TransactionRequest { - gas?: BigNumberish -} +import { TransactionListenerProcessIndex } from '@multiplechain/types' + +export class TransactionListener + implements TransactionListenerInterface +{ + /** + * Transaction type + */ + type: T + + /** + * Transaction listener callback + */ + callbacks: TransactionListenerCallbackType[] = [] + + /** + * Transaction listener filter + */ + filter: DynamicTransactionListenerFilterType -const { ethers } = Provider.instance + /** + * @param type - Transaction type + * @param filter - Transaction listener filter + */ + constructor(type: T, filter: DynamicTransactionListenerFilterType) { + this.type = type + this.filter = filter + // @ts-expect-error allow dynamic access + this[TransactionListenerProcessIndex[type]]() + } + + /** + * Close the listener + */ + stop(): void { + // Close the listener + } -export class TransactionSigner implements TransactionSignerInterface { /** - * Transaction data from the blockchain network + * Listen to the transaction events + * @param callback - Callback function */ - rawData: TransactionData + on(callback: TransactionListenerCallbackType): void { + this.callbacks.push(callback) + } /** - * Signed transaction data + * Trigger the event when a transaction is detected + * @param transaction - Transaction data */ - signedData: string + trigger(transaction: DynamicTransactionType): void { + this.callbacks.forEach((callback) => { + callback(transaction) + }) + } /** - * Wallet instance from ethers with the private key + * General transaction process */ - wallet: Wallet + generalProcess(): void { + // General transaction process + } /** - * @param rawData - Transaction data + * Contract transaction process */ - constructor(rawData: TransactionData) { - this.rawData = rawData + contractProcess(): void { + // Contract transaction process } /** - * Sign the transaction - * @param privateKey - Transaction data + * Asset transaction process */ - public async sign(privateKey: string): Promise { - this.wallet = ethers.wallet(privateKey) - this.signedData = await this.wallet.signTransaction(this.rawData) - return this + assetProcess(): void { + // Asset transaction process } /** - * Send the transaction to the blockchain network - * @returns Promise of the transaction + * Coin transaction process */ - async send(): Promise { - return new Transaction( - (await ethers.jsonRpc.send('eth_sendRawTransaction', [this.signedData])) as string - ) + coinProcess(): void { + // Coin transaction process } /** - * Get the raw transaction data - * @returns Transaction data + * Token transaction process */ - getRawData(): any { - return this.rawData + tokenProcess(): void { + // Token transaction process } /** - * Get the signed transaction data - * @returns Signed transaction data + * NFT transaction process */ - getSignedData(): any { - return this.signedData + nftProcess(): void { + // NFT transaction process } } diff --git a/packages/types/src/enums.ts b/packages/types/src/enums.ts old mode 100644 new mode 100755 index 444f739..7f01da7 --- a/packages/types/src/enums.ts +++ b/packages/types/src/enums.ts @@ -13,7 +13,6 @@ export enum AssetDirectionEnum { export enum TransactionTypeEnum { GENERAL = 'GENERAL', CONTRACT = 'CONTRACT', - ASSET = 'ASSET', COIN = 'COIN', TOKEN = 'TOKEN', NFT = 'NFT' From 4a148ffa2308bb811d7c1fabb3c51bcf71aaf57d Mon Sep 17 00:00:00 2001 From: Halil Beycan <50718965+BeycanDeveloper@users.noreply.github.com> Date: Wed, 27 Mar 2024 19:49:23 +0800 Subject: [PATCH 029/114] Revert "transaction signer types + NFT asset" This reverts commit 8444f733359c8f63415cb56ef0d25e79c856556f. --- .../networks/evm-chains/src/assets/Coin.ts | 0 .../evm-chains/src/assets/Contract.ts | 0 .../networks/evm-chains/src/assets/NFT.ts | 147 ++++------------- .../networks/evm-chains/src/assets/Token.ts | 28 +--- .../src/services/TransactionListener.ts | 149 ++++++++---------- .../src/services/TransactionSigner.ts | 112 +++++-------- packages/types/src/enums.ts | 1 + 7 files changed, 140 insertions(+), 297 deletions(-) mode change 100755 => 100644 packages/networks/evm-chains/src/assets/Coin.ts mode change 100755 => 100644 packages/networks/evm-chains/src/assets/Contract.ts mode change 100755 => 100644 packages/networks/evm-chains/src/assets/NFT.ts mode change 100755 => 100644 packages/networks/evm-chains/src/assets/Token.ts mode change 100755 => 100644 packages/networks/evm-chains/src/services/TransactionListener.ts mode change 100755 => 100644 packages/networks/evm-chains/src/services/TransactionSigner.ts mode change 100755 => 100644 packages/types/src/enums.ts diff --git a/packages/networks/evm-chains/src/assets/Coin.ts b/packages/networks/evm-chains/src/assets/Coin.ts old mode 100755 new mode 100644 diff --git a/packages/networks/evm-chains/src/assets/Contract.ts b/packages/networks/evm-chains/src/assets/Contract.ts old mode 100755 new mode 100644 diff --git a/packages/networks/evm-chains/src/assets/NFT.ts b/packages/networks/evm-chains/src/assets/NFT.ts old mode 100755 new mode 100644 index 5ec6704..4d7ebfc --- a/packages/networks/evm-chains/src/assets/NFT.ts +++ b/packages/networks/evm-chains/src/assets/NFT.ts @@ -1,161 +1,68 @@ import { Contract } from './Contract.ts' import ERC721 from '../../resources/erc721.json' -import { Provider } from '../services/Provider.ts' import { TransactionSigner } from '../services/TransactionSigner.ts' -import { ErrorTypeEnum, type NftInterface } from '@multiplechain/types' +import type { NftInterface, TransactionSignerInterface } from '@multiplechain/types' export class NFT extends Contract implements NftInterface { - constructor(address: string) { - super(address, ERC721) - } - /** * @returns Contract name */ - async getName(): Promise { - return await this.callMethod('name') + getName(): string { + return 'example' } /** * @returns Contract symbol */ - async getSymbol(): Promise { - return await this.callMethod('symbol') + getSymbol(): string { + return 'example' } /** * @param owner Wallet address - * @returns Number of tokens of owner + * @returns Wallet balance as currency of TOKEN or COIN assets */ - async getBalance(owner: string): Promise { - return await this.ethersContract.balanceOf(owner) + getBalance(owner: string): number { + return 0 } /** - * @param sender Sender address - * @param receiver Receiver address - * @param nftId NFT ID - * @returns Transaction signer + * @returns Contract address */ - async transfer(sender: string, receiver: string, nftId: number): Promise { - // Check if tokens exist - const balance = await this.getBalance(sender) - - if (balance <= 0) { - throw new Error(ErrorTypeEnum.INSUFFICIENT_BALANCE) - } - - // Check ownership - const originalOwner = await this.getOwner(nftId) - if (originalOwner !== sender) { - throw new Error(ErrorTypeEnum.UNAUTHORIZED_ADDRESS) - } - - const { network, ethers } = Provider.instance - - const [gasPrice, nonce, data, gasLimit] = await Promise.all([ - ethers.getGasPrice(), - ethers.getNonce(sender), - this.getMethodData('transfer', receiver, nftId), - this.getMethodEstimateGas('transfer', sender, receiver, nftId) - ]) - - return new TransactionSigner({ - data, - nonce, - gasPrice, - gasLimit, - value: '0x0', - from: sender, - chainId: network.id, - to: receiver - }) - } - - async transferFrom( - spender: string, - owner: string, - receiver: string, - nftId: number - ): Promise { - // Check if tokens exist - const balance = await this.getBalance(owner) - - if (balance <= 0) { - throw new Error(ErrorTypeEnum.INSUFFICIENT_BALANCE) - } - - // Check ownership - const originalOwner = await this.getOwner(nftId) - if (originalOwner !== owner) { - throw new Error(ErrorTypeEnum.UNAUTHORIZED_ADDRESS) - } - - // + getAddress(): string { + return 'example' } /** - * @param nftId NFT ID - * @returns NFT owner wallet address + * @returns NFT ID */ - async getOwner(nftId: number): Promise { - return await this.ethersContract.ownerOf(nftId) + getNftId(): number { + return 0 } /** + * @param sender Sender address + * @param receiver Receiver address * @param nftId NFT ID - * @returns NFT URI + * @returns Transaction signer */ - async getTokenURI(nftId: number): Promise { - return await this.ethersContract.tokenURI(nftId) + transfer(sender: string, receiver: string, nftId: number): TransactionSignerInterface { + return new TransactionSigner('example') } /** - * Gives permission to the spender to spend owner's tokens - * @param owner Address of owner of the tokens that will be used - * @param spender Address of the spender that will use the tokens of owner - * @param nftId ID of the NFT that will be transferred + * @param nftId NFT ID + * @returns NFT owner wallet address */ - async approve(owner: string, spender: string, nftId: number): Promise { - // Check if tokens exist - const balance = await this.getBalance(owner) - - if (balance <= 0) { - throw new Error(ErrorTypeEnum.INSUFFICIENT_BALANCE) - } - - // Check ownership - const originalOwner = await this.getOwner(nftId) - if (originalOwner !== owner) { - throw new Error(ErrorTypeEnum.UNAUTHORIZED_ADDRESS) - } - - const { network, ethers } = Provider.instance - - const [gasPrice, nonce, data, gasLimit] = await Promise.all([ - ethers.getGasPrice(), - ethers.getNonce(owner), - this.getMethodData('approve', spender, nftId), - this.getMethodEstimateGas('approve', owner, spender, nftId) - ]) - - return new TransactionSigner({ - data, - nonce, - gasPrice, - gasLimit, - value: '0x0', - from: owner, - chainId: network.id, - to: spender - }) + getOwner(nftId: number): string { + return 'example' } /** - * @param nftId ID of the NFT that will be transferred - * @returns Amount of the tokens that is being used by spender + * @param nftId NFT ID + * @returns NFT URI */ - async getApproved(nftId: number): Promise { - return await this.ethersContract.getApproved(nftId) + getTokenURI(nftId: number): string { + return 'example' } } diff --git a/packages/networks/evm-chains/src/assets/Token.ts b/packages/networks/evm-chains/src/assets/Token.ts old mode 100755 new mode 100644 index d1750c7..5ba94eb --- a/packages/networks/evm-chains/src/assets/Token.ts +++ b/packages/networks/evm-chains/src/assets/Token.ts @@ -1,10 +1,9 @@ -import { hexToNumber, numberToHex } from '@multiplechain/utils' -import { ErrorTypeEnum, type TokenInterface } from '@multiplechain/types' - import { Contract } from './Contract.ts' import ERC20 from '../../resources/erc20.json' import { Provider } from '../services/Provider.ts' import { TransactionSigner } from '../services/TransactionSigner.ts' +import { hexToNumber, numberToHex } from '@multiplechain/utils' +import type { TokenInterface } from '@multiplechain/types' export class Token extends Contract implements TokenInterface { constructor(address: string) { @@ -90,25 +89,6 @@ export class Token extends Contract implements TokenInterface { }) } - /** - * transferFrom() transfers tokens from sender to receiver using allowance - * @param sender Sender wallet address - * @param receiver Receiver wallet address - * @param amount Amount of assets that will be transferred - */ - async transferFrom( - spender: string, - owner: string, - receiver: string, - amount: number - ): Promise { - if (amount < 0) { - throw new Error(ErrorTypeEnum.INVALID_AMOUNT) - } - - // - } - /** * Gives permission to the spender to spend owner's tokens * @param owner Address of owner of the tokens that will be used @@ -117,13 +97,13 @@ export class Token extends Contract implements TokenInterface { */ async approve(owner: string, spender: string, amount: number): Promise { if (amount < 0) { - throw new Error(ErrorTypeEnum.INVALID_AMOUNT) + throw new Error('Invalid amount') } const [balance, decimals] = await Promise.all([this.getBalance(owner), this.getDecimals()]) if (amount > balance) { - throw new Error(ErrorTypeEnum.INSUFFICIENT_BALANCE) + throw new Error('Insufficient balance') } const { network, ethers } = Provider.instance diff --git a/packages/networks/evm-chains/src/services/TransactionListener.ts b/packages/networks/evm-chains/src/services/TransactionListener.ts old mode 100755 new mode 100644 index 985269d..5382093 --- a/packages/networks/evm-chains/src/services/TransactionListener.ts +++ b/packages/networks/evm-chains/src/services/TransactionListener.ts @@ -1,115 +1,106 @@ -import { Provider } from '../services/Provider.ts' -import type { TransactionRequest, Wallet, BigNumberish } from 'ethers' -import { TransactionTypeEnum, type TransactionSignerInterface } from '@multiplechain/types' - -// Transactions -import { Transaction } from '../models/Transaction.ts' -import { NftTransaction } from '../models/NftTransaction.ts' -import { CoinTransaction } from '../models/CoinTransaction.ts' -import { TokenTransaction } from '../models/TokenTransaction.ts' -import { ContractTransaction } from '../models/ContractTransaction.ts' - -export interface TransactionData extends TransactionRequest { - gas?: BigNumberish -} - -const { ethers } = Provider.instance - -export class TransactionSigner implements TransactionSignerInterface { +import type { + TransactionTypeEnum, + DynamicTransactionType, + TransactionListenerInterface, + TransactionListenerCallbackType, + DynamicTransactionListenerFilterType +} from '@multiplechain/types' + +import { TransactionListenerProcessIndex } from '@multiplechain/types' + +export class TransactionListener + implements TransactionListenerInterface +{ /** - * Transaction data from the blockchain network + * Transaction type */ - rawData: TransactionData + type: T /** - * Transaction type + * Transaction listener callback */ - type: TransactionTypeEnum + callbacks: TransactionListenerCallbackType[] = [] /** - * Signed transaction data + * Transaction listener filter */ - signedData: string + filter: DynamicTransactionListenerFilterType /** - * Wallet instance from ethers with the private key + * @param type - Transaction type + * @param filter - Transaction listener filter */ - wallet: Wallet + constructor(type: T, filter: DynamicTransactionListenerFilterType) { + this.type = type + this.filter = filter + // @ts-expect-error allow dynamic access + this[TransactionListenerProcessIndex[type]]() + } /** - * @param rawData - Transaction data + * Close the listener */ - constructor(rawData: TransactionData, type?: TransactionTypeEnum) { - this.rawData = rawData - if (type !== undefined) this.type = type + stop(): void { + // Close the listener } /** - * Sign the transaction - * @param privateKey - Transaction data + * Listen to the transaction events + * @param callback - Callback function */ - public async sign(privateKey: string): Promise { - this.wallet = ethers.wallet(privateKey) - this.signedData = await this.wallet.signTransaction(this.rawData) - return this + on(callback: TransactionListenerCallbackType): void { + this.callbacks.push(callback) } /** - * Send the transaction to the blockchain network - * @returns Promise of the transaction + * Trigger the event when a transaction is detected + * @param transaction - Transaction data */ - async send(): Promise { - switch (this.type) { - case TransactionTypeEnum.COIN: - return new CoinTransaction( - (await ethers.jsonRpc.send('eth_sendRawTransaction', [ - this.signedData - ])) as string - ) + trigger(transaction: DynamicTransactionType): void { + this.callbacks.forEach((callback) => { + callback(transaction) + }) + } - case TransactionTypeEnum.TOKEN: - return new TokenTransaction( - (await ethers.jsonRpc.send('eth_sendRawTransaction', [ - this.signedData - ])) as string - ) + /** + * General transaction process + */ + generalProcess(): void { + // General transaction process + } - case TransactionTypeEnum.NFT: - return new NftTransaction( - (await ethers.jsonRpc.send('eth_sendRawTransaction', [ - this.signedData - ])) as string - ) + /** + * Contract transaction process + */ + contractProcess(): void { + // Contract transaction process + } - case TransactionTypeEnum.CONTRACT: - return new ContractTransaction( - (await ethers.jsonRpc.send('eth_sendRawTransaction', [ - this.signedData - ])) as string - ) + /** + * Asset transaction process + */ + assetProcess(): void { + // Asset transaction process + } - default: - return new Transaction( - (await ethers.jsonRpc.send('eth_sendRawTransaction', [ - this.signedData - ])) as string - ) - } + /** + * Coin transaction process + */ + coinProcess(): void { + // Coin transaction process } /** - * Get the raw transaction data - * @returns Transaction data + * Token transaction process */ - getRawData(): any { - return this.rawData + tokenProcess(): void { + // Token transaction process } /** - * Get the signed transaction data - * @returns Signed transaction data + * NFT transaction process */ - getSignedData(): any { - return this.signedData + nftProcess(): void { + // NFT transaction process } } diff --git a/packages/networks/evm-chains/src/services/TransactionSigner.ts b/packages/networks/evm-chains/src/services/TransactionSigner.ts old mode 100755 new mode 100644 index 5382093..0ae63df --- a/packages/networks/evm-chains/src/services/TransactionSigner.ts +++ b/packages/networks/evm-chains/src/services/TransactionSigner.ts @@ -1,106 +1,70 @@ -import type { - TransactionTypeEnum, - DynamicTransactionType, - TransactionListenerInterface, - TransactionListenerCallbackType, - DynamicTransactionListenerFilterType -} from '@multiplechain/types' +import { Provider } from '../services/Provider.ts' +import { Transaction } from '../models/Transaction.ts' +import type { TransactionRequest, Wallet, BigNumberish } from 'ethers' +import type { TransactionSignerInterface } from '@multiplechain/types' -import { TransactionListenerProcessIndex } from '@multiplechain/types' - -export class TransactionListener - implements TransactionListenerInterface -{ - /** - * Transaction type - */ - type: T - - /** - * Transaction listener callback - */ - callbacks: TransactionListenerCallbackType[] = [] - - /** - * Transaction listener filter - */ - filter: DynamicTransactionListenerFilterType - - /** - * @param type - Transaction type - * @param filter - Transaction listener filter - */ - constructor(type: T, filter: DynamicTransactionListenerFilterType) { - this.type = type - this.filter = filter - // @ts-expect-error allow dynamic access - this[TransactionListenerProcessIndex[type]]() - } +export interface TransactionData extends TransactionRequest { + gas?: BigNumberish +} - /** - * Close the listener - */ - stop(): void { - // Close the listener - } +const { ethers } = Provider.instance +export class TransactionSigner implements TransactionSignerInterface { /** - * Listen to the transaction events - * @param callback - Callback function + * Transaction data from the blockchain network */ - on(callback: TransactionListenerCallbackType): void { - this.callbacks.push(callback) - } + rawData: TransactionData /** - * Trigger the event when a transaction is detected - * @param transaction - Transaction data + * Signed transaction data */ - trigger(transaction: DynamicTransactionType): void { - this.callbacks.forEach((callback) => { - callback(transaction) - }) - } + signedData: string /** - * General transaction process + * Wallet instance from ethers with the private key */ - generalProcess(): void { - // General transaction process - } + wallet: Wallet /** - * Contract transaction process + * @param rawData - Transaction data */ - contractProcess(): void { - // Contract transaction process + constructor(rawData: TransactionData) { + this.rawData = rawData } /** - * Asset transaction process + * Sign the transaction + * @param privateKey - Transaction data */ - assetProcess(): void { - // Asset transaction process + public async sign(privateKey: string): Promise { + this.wallet = ethers.wallet(privateKey) + this.signedData = await this.wallet.signTransaction(this.rawData) + return this } /** - * Coin transaction process + * Send the transaction to the blockchain network + * @returns Promise of the transaction */ - coinProcess(): void { - // Coin transaction process + async send(): Promise { + return new Transaction( + (await ethers.jsonRpc.send('eth_sendRawTransaction', [this.signedData])) as string + ) } /** - * Token transaction process + * Get the raw transaction data + * @returns Transaction data */ - tokenProcess(): void { - // Token transaction process + getRawData(): any { + return this.rawData } /** - * NFT transaction process + * Get the signed transaction data + * @returns Signed transaction data */ - nftProcess(): void { - // NFT transaction process + getSignedData(): any { + return this.signedData } } diff --git a/packages/types/src/enums.ts b/packages/types/src/enums.ts old mode 100755 new mode 100644 index 7f01da7..444f739 --- a/packages/types/src/enums.ts +++ b/packages/types/src/enums.ts @@ -13,6 +13,7 @@ export enum AssetDirectionEnum { export enum TransactionTypeEnum { GENERAL = 'GENERAL', CONTRACT = 'CONTRACT', + ASSET = 'ASSET', COIN = 'COIN', TOKEN = 'TOKEN', NFT = 'NFT' From 01687e02a84ed7f250f8c53b632b1a355a3de682 Mon Sep 17 00:00:00 2001 From: oynozan Date: Wed, 27 Mar 2024 15:00:35 +0300 Subject: [PATCH 030/114] transaction signer types + NFT asset --- .../networks/evm-chains/src/assets/NFT.ts | 147 ++++++++++++++---- .../networks/evm-chains/src/assets/Token.ts | 28 +++- .../src/services/TransactionSigner.ts | 57 ++++++- packages/types/src/enums.ts | 1 - 4 files changed, 195 insertions(+), 38 deletions(-) diff --git a/packages/networks/evm-chains/src/assets/NFT.ts b/packages/networks/evm-chains/src/assets/NFT.ts index 4d7ebfc..5ec6704 100644 --- a/packages/networks/evm-chains/src/assets/NFT.ts +++ b/packages/networks/evm-chains/src/assets/NFT.ts @@ -1,68 +1,161 @@ import { Contract } from './Contract.ts' import ERC721 from '../../resources/erc721.json' +import { Provider } from '../services/Provider.ts' import { TransactionSigner } from '../services/TransactionSigner.ts' -import type { NftInterface, TransactionSignerInterface } from '@multiplechain/types' +import { ErrorTypeEnum, type NftInterface } from '@multiplechain/types' export class NFT extends Contract implements NftInterface { + constructor(address: string) { + super(address, ERC721) + } + /** * @returns Contract name */ - getName(): string { - return 'example' + async getName(): Promise { + return await this.callMethod('name') } /** * @returns Contract symbol */ - getSymbol(): string { - return 'example' + async getSymbol(): Promise { + return await this.callMethod('symbol') } /** * @param owner Wallet address - * @returns Wallet balance as currency of TOKEN or COIN assets + * @returns Number of tokens of owner */ - getBalance(owner: string): number { - return 0 + async getBalance(owner: string): Promise { + return await this.ethersContract.balanceOf(owner) } /** - * @returns Contract address + * @param sender Sender address + * @param receiver Receiver address + * @param nftId NFT ID + * @returns Transaction signer */ - getAddress(): string { - return 'example' + async transfer(sender: string, receiver: string, nftId: number): Promise { + // Check if tokens exist + const balance = await this.getBalance(sender) + + if (balance <= 0) { + throw new Error(ErrorTypeEnum.INSUFFICIENT_BALANCE) + } + + // Check ownership + const originalOwner = await this.getOwner(nftId) + if (originalOwner !== sender) { + throw new Error(ErrorTypeEnum.UNAUTHORIZED_ADDRESS) + } + + const { network, ethers } = Provider.instance + + const [gasPrice, nonce, data, gasLimit] = await Promise.all([ + ethers.getGasPrice(), + ethers.getNonce(sender), + this.getMethodData('transfer', receiver, nftId), + this.getMethodEstimateGas('transfer', sender, receiver, nftId) + ]) + + return new TransactionSigner({ + data, + nonce, + gasPrice, + gasLimit, + value: '0x0', + from: sender, + chainId: network.id, + to: receiver + }) + } + + async transferFrom( + spender: string, + owner: string, + receiver: string, + nftId: number + ): Promise { + // Check if tokens exist + const balance = await this.getBalance(owner) + + if (balance <= 0) { + throw new Error(ErrorTypeEnum.INSUFFICIENT_BALANCE) + } + + // Check ownership + const originalOwner = await this.getOwner(nftId) + if (originalOwner !== owner) { + throw new Error(ErrorTypeEnum.UNAUTHORIZED_ADDRESS) + } + + // } /** - * @returns NFT ID + * @param nftId NFT ID + * @returns NFT owner wallet address */ - getNftId(): number { - return 0 + async getOwner(nftId: number): Promise { + return await this.ethersContract.ownerOf(nftId) } /** - * @param sender Sender address - * @param receiver Receiver address * @param nftId NFT ID - * @returns Transaction signer + * @returns NFT URI */ - transfer(sender: string, receiver: string, nftId: number): TransactionSignerInterface { - return new TransactionSigner('example') + async getTokenURI(nftId: number): Promise { + return await this.ethersContract.tokenURI(nftId) } /** - * @param nftId NFT ID - * @returns NFT owner wallet address + * Gives permission to the spender to spend owner's tokens + * @param owner Address of owner of the tokens that will be used + * @param spender Address of the spender that will use the tokens of owner + * @param nftId ID of the NFT that will be transferred */ - getOwner(nftId: number): string { - return 'example' + async approve(owner: string, spender: string, nftId: number): Promise { + // Check if tokens exist + const balance = await this.getBalance(owner) + + if (balance <= 0) { + throw new Error(ErrorTypeEnum.INSUFFICIENT_BALANCE) + } + + // Check ownership + const originalOwner = await this.getOwner(nftId) + if (originalOwner !== owner) { + throw new Error(ErrorTypeEnum.UNAUTHORIZED_ADDRESS) + } + + const { network, ethers } = Provider.instance + + const [gasPrice, nonce, data, gasLimit] = await Promise.all([ + ethers.getGasPrice(), + ethers.getNonce(owner), + this.getMethodData('approve', spender, nftId), + this.getMethodEstimateGas('approve', owner, spender, nftId) + ]) + + return new TransactionSigner({ + data, + nonce, + gasPrice, + gasLimit, + value: '0x0', + from: owner, + chainId: network.id, + to: spender + }) } /** - * @param nftId NFT ID - * @returns NFT URI + * @param nftId ID of the NFT that will be transferred + * @returns Amount of the tokens that is being used by spender */ - getTokenURI(nftId: number): string { - return 'example' + async getApproved(nftId: number): Promise { + return await this.ethersContract.getApproved(nftId) } } diff --git a/packages/networks/evm-chains/src/assets/Token.ts b/packages/networks/evm-chains/src/assets/Token.ts index 5ba94eb..d1750c7 100644 --- a/packages/networks/evm-chains/src/assets/Token.ts +++ b/packages/networks/evm-chains/src/assets/Token.ts @@ -1,9 +1,10 @@ +import { hexToNumber, numberToHex } from '@multiplechain/utils' +import { ErrorTypeEnum, type TokenInterface } from '@multiplechain/types' + import { Contract } from './Contract.ts' import ERC20 from '../../resources/erc20.json' import { Provider } from '../services/Provider.ts' import { TransactionSigner } from '../services/TransactionSigner.ts' -import { hexToNumber, numberToHex } from '@multiplechain/utils' -import type { TokenInterface } from '@multiplechain/types' export class Token extends Contract implements TokenInterface { constructor(address: string) { @@ -89,6 +90,25 @@ export class Token extends Contract implements TokenInterface { }) } + /** + * transferFrom() transfers tokens from sender to receiver using allowance + * @param sender Sender wallet address + * @param receiver Receiver wallet address + * @param amount Amount of assets that will be transferred + */ + async transferFrom( + spender: string, + owner: string, + receiver: string, + amount: number + ): Promise { + if (amount < 0) { + throw new Error(ErrorTypeEnum.INVALID_AMOUNT) + } + + // + } + /** * Gives permission to the spender to spend owner's tokens * @param owner Address of owner of the tokens that will be used @@ -97,13 +117,13 @@ export class Token extends Contract implements TokenInterface { */ async approve(owner: string, spender: string, amount: number): Promise { if (amount < 0) { - throw new Error('Invalid amount') + throw new Error(ErrorTypeEnum.INVALID_AMOUNT) } const [balance, decimals] = await Promise.all([this.getBalance(owner), this.getDecimals()]) if (amount > balance) { - throw new Error('Insufficient balance') + throw new Error(ErrorTypeEnum.INSUFFICIENT_BALANCE) } const { network, ethers } = Provider.instance diff --git a/packages/networks/evm-chains/src/services/TransactionSigner.ts b/packages/networks/evm-chains/src/services/TransactionSigner.ts index 0ae63df..985269d 100644 --- a/packages/networks/evm-chains/src/services/TransactionSigner.ts +++ b/packages/networks/evm-chains/src/services/TransactionSigner.ts @@ -1,7 +1,13 @@ import { Provider } from '../services/Provider.ts' -import { Transaction } from '../models/Transaction.ts' import type { TransactionRequest, Wallet, BigNumberish } from 'ethers' -import type { TransactionSignerInterface } from '@multiplechain/types' +import { TransactionTypeEnum, type TransactionSignerInterface } from '@multiplechain/types' + +// Transactions +import { Transaction } from '../models/Transaction.ts' +import { NftTransaction } from '../models/NftTransaction.ts' +import { CoinTransaction } from '../models/CoinTransaction.ts' +import { TokenTransaction } from '../models/TokenTransaction.ts' +import { ContractTransaction } from '../models/ContractTransaction.ts' export interface TransactionData extends TransactionRequest { gas?: BigNumberish @@ -15,6 +21,11 @@ export class TransactionSigner implements TransactionSignerInterface { */ rawData: TransactionData + /** + * Transaction type + */ + type: TransactionTypeEnum + /** * Signed transaction data */ @@ -28,8 +39,9 @@ export class TransactionSigner implements TransactionSignerInterface { /** * @param rawData - Transaction data */ - constructor(rawData: TransactionData) { + constructor(rawData: TransactionData, type?: TransactionTypeEnum) { this.rawData = rawData + if (type !== undefined) this.type = type } /** @@ -47,9 +59,42 @@ export class TransactionSigner implements TransactionSignerInterface { * @returns Promise of the transaction */ async send(): Promise { - return new Transaction( - (await ethers.jsonRpc.send('eth_sendRawTransaction', [this.signedData])) as string - ) + switch (this.type) { + case TransactionTypeEnum.COIN: + return new CoinTransaction( + (await ethers.jsonRpc.send('eth_sendRawTransaction', [ + this.signedData + ])) as string + ) + + case TransactionTypeEnum.TOKEN: + return new TokenTransaction( + (await ethers.jsonRpc.send('eth_sendRawTransaction', [ + this.signedData + ])) as string + ) + + case TransactionTypeEnum.NFT: + return new NftTransaction( + (await ethers.jsonRpc.send('eth_sendRawTransaction', [ + this.signedData + ])) as string + ) + + case TransactionTypeEnum.CONTRACT: + return new ContractTransaction( + (await ethers.jsonRpc.send('eth_sendRawTransaction', [ + this.signedData + ])) as string + ) + + default: + return new Transaction( + (await ethers.jsonRpc.send('eth_sendRawTransaction', [ + this.signedData + ])) as string + ) + } } /** diff --git a/packages/types/src/enums.ts b/packages/types/src/enums.ts index 444f739..7f01da7 100644 --- a/packages/types/src/enums.ts +++ b/packages/types/src/enums.ts @@ -13,7 +13,6 @@ export enum AssetDirectionEnum { export enum TransactionTypeEnum { GENERAL = 'GENERAL', CONTRACT = 'CONTRACT', - ASSET = 'ASSET', COIN = 'COIN', TOKEN = 'TOKEN', NFT = 'NFT' From 676790bb04bb36f72dfc03fd5a4a25674dc054ab Mon Sep 17 00:00:00 2001 From: Halil Beycan <50718965+BeycanDeveloper@users.noreply.github.com> Date: Wed, 27 Mar 2024 20:15:58 +0800 Subject: [PATCH 031/114] added verifyApprove for nft model --- packages/types/package.json | 2 +- packages/types/src/models.ts | 11 +++++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/packages/types/package.json b/packages/types/package.json index b61c1f7..3b8a84c 100644 --- a/packages/types/package.json +++ b/packages/types/package.json @@ -1,6 +1,6 @@ { "name": "@multiplechain/types", - "version": "0.1.21", + "version": "0.1.22", "type": "module", "main": "./src/index.ts", "types": "./src/index.ts", diff --git a/packages/types/src/models.ts b/packages/types/src/models.ts index 767d224..a6e8992 100644 --- a/packages/types/src/models.ts +++ b/packages/types/src/models.ts @@ -124,4 +124,15 @@ export interface NftTransactionInterface address: string, nftId: number ) => Promise + + /** + * @param direction - Direction of the transaction (nft) + * @param address - Wallet address of the owner or spender of the transaction, dependant on direction + * @param nftId ID of the NFT that will be approved + */ + verifyApprove: ( + direction: AssetDirectionEnum, + address: string, + nftId: number + ) => Promise } From e320257d2611f9f8cf16c932a3f61769983d85e8 Mon Sep 17 00:00:00 2001 From: Halil Beycan <50718965+BeycanDeveloper@users.noreply.github.com> Date: Wed, 27 Mar 2024 20:19:58 +0800 Subject: [PATCH 032/114] send method updated --- packages/networks/boilerplate/package.json | 2 +- packages/networks/evm-chains/package.json | 2 +- packages/networks/evm-chains/pnpm-lock.yaml | 8 ++-- .../src/services/TransactionSigner.ts | 37 +++++-------------- 4 files changed, 16 insertions(+), 33 deletions(-) diff --git a/packages/networks/boilerplate/package.json b/packages/networks/boilerplate/package.json index 5e81567..4b33230 100644 --- a/packages/networks/boilerplate/package.json +++ b/packages/networks/boilerplate/package.json @@ -36,7 +36,7 @@ "url": "https://github.com/MultipleChain/js/issues" }, "dependencies": { - "@multiplechain/types": "^0.1.21", + "@multiplechain/types": "^0.1.22", "@multiplechain/utils": "^0.1.8" } } \ No newline at end of file diff --git a/packages/networks/evm-chains/package.json b/packages/networks/evm-chains/package.json index c6f23db..308c720 100644 --- a/packages/networks/evm-chains/package.json +++ b/packages/networks/evm-chains/package.json @@ -38,7 +38,7 @@ "url": "https://github.com/MultipleChain/js/issues" }, "dependencies": { - "@multiplechain/types": "^0.1.21", + "@multiplechain/types": "^0.1.22", "@multiplechain/utils": "^0.1.9" } } \ No newline at end of file diff --git a/packages/networks/evm-chains/pnpm-lock.yaml b/packages/networks/evm-chains/pnpm-lock.yaml index 62e8f1b..3d6dd36 100644 --- a/packages/networks/evm-chains/pnpm-lock.yaml +++ b/packages/networks/evm-chains/pnpm-lock.yaml @@ -6,16 +6,16 @@ settings: dependencies: '@multiplechain/types': - specifier: ^0.1.21 - version: 0.1.21 + specifier: ^0.1.22 + version: 0.1.22 '@multiplechain/utils': specifier: ^0.1.9 version: 0.1.9 packages: - /@multiplechain/types@0.1.21: - resolution: {integrity: sha512-x42yGCAGUEFPdhbyMw3tyZ9eAWztR8EIWdg7JkVedfnWZ4E0y6hIcr+HMInP2zJpQZIh+w73k94bJyoHklOjFg==} + /@multiplechain/types@0.1.22: + resolution: {integrity: sha512-0150RfkScgb+qDf5GFiAmFCsuIsQmjCUqvLv0n4JSUuhIkZA45NOwypo2UYOgBx6JiLyHLs4vqf9VUWaaUMTeA==} dev: false /@multiplechain/utils@0.1.9: diff --git a/packages/networks/evm-chains/src/services/TransactionSigner.ts b/packages/networks/evm-chains/src/services/TransactionSigner.ts index 985269d..7d4558d 100644 --- a/packages/networks/evm-chains/src/services/TransactionSigner.ts +++ b/packages/networks/evm-chains/src/services/TransactionSigner.ts @@ -24,7 +24,7 @@ export class TransactionSigner implements TransactionSignerInterface { /** * Transaction type */ - type: TransactionTypeEnum + type?: TransactionTypeEnum /** * Signed transaction data @@ -40,8 +40,8 @@ export class TransactionSigner implements TransactionSignerInterface { * @param rawData - Transaction data */ constructor(rawData: TransactionData, type?: TransactionTypeEnum) { + this.type = type this.rawData = rawData - if (type !== undefined) this.type = type } /** @@ -59,41 +59,24 @@ export class TransactionSigner implements TransactionSignerInterface { * @returns Promise of the transaction */ async send(): Promise { + const txId = (await ethers.jsonRpc.send('eth_sendRawTransaction', [ + this.signedData + ])) as string switch (this.type) { case TransactionTypeEnum.COIN: - return new CoinTransaction( - (await ethers.jsonRpc.send('eth_sendRawTransaction', [ - this.signedData - ])) as string - ) + return new CoinTransaction(txId) case TransactionTypeEnum.TOKEN: - return new TokenTransaction( - (await ethers.jsonRpc.send('eth_sendRawTransaction', [ - this.signedData - ])) as string - ) + return new TokenTransaction(txId) case TransactionTypeEnum.NFT: - return new NftTransaction( - (await ethers.jsonRpc.send('eth_sendRawTransaction', [ - this.signedData - ])) as string - ) + return new NftTransaction(txId) case TransactionTypeEnum.CONTRACT: - return new ContractTransaction( - (await ethers.jsonRpc.send('eth_sendRawTransaction', [ - this.signedData - ])) as string - ) + return new ContractTransaction(txId) default: - return new Transaction( - (await ethers.jsonRpc.send('eth_sendRawTransaction', [ - this.signedData - ])) as string - ) + return new Transaction(txId) } } From 304f155ac705d63171c4842d775c47797aafbe0d Mon Sep 17 00:00:00 2001 From: Halil Beycan <50718965+BeycanDeveloper@users.noreply.github.com> Date: Wed, 27 Mar 2024 20:26:07 +0800 Subject: [PATCH 033/114] updated --- packages/types/README.md | 16 ++++----- packages/types/package.json | 2 +- .../services/TransactionListenerInterface.ts | 36 ++++++++----------- 3 files changed, 22 insertions(+), 32 deletions(-) diff --git a/packages/types/README.md b/packages/types/README.md index 39c495e..4f45a25 100644 --- a/packages/types/README.md +++ b/packages/types/README.md @@ -168,15 +168,13 @@ export type DynamicTransactionType = ? TransactionInterface : T extends TransactionTypeEnum.CONTRACT ? ContractTransactionInterface - : T extends TransactionTypeEnum.ASSET - ? AssetTransactionInterface - : T extends TransactionTypeEnum.COIN - ? CoinTransactionInterface - : T extends TransactionTypeEnum.TOKEN - ? TokenTransactionInterface - : T extends TransactionTypeEnum.NFT - ? NftTransactionInterface - : never + : T extends TransactionTypeEnum.COIN + ? CoinTransactionInterface + : T extends TransactionTypeEnum.TOKEN + ? TokenTransactionInterface + : T extends TransactionTypeEnum.NFT + ? NftTransactionInterface + : never ``` #### [DynamicTransactionListenerFilterType](./packages/types/src/services/TransactionListenerInterface.ts) diff --git a/packages/types/package.json b/packages/types/package.json index 3b8a84c..8780b43 100644 --- a/packages/types/package.json +++ b/packages/types/package.json @@ -1,6 +1,6 @@ { "name": "@multiplechain/types", - "version": "0.1.22", + "version": "0.1.23", "type": "module", "main": "./src/index.ts", "types": "./src/index.ts", diff --git a/packages/types/src/services/TransactionListenerInterface.ts b/packages/types/src/services/TransactionListenerInterface.ts index 680c589..9452446 100644 --- a/packages/types/src/services/TransactionListenerInterface.ts +++ b/packages/types/src/services/TransactionListenerInterface.ts @@ -1,7 +1,6 @@ import type { TransactionInterface, ContractTransactionInterface, - AssetTransactionInterface, CoinTransactionInterface, TokenTransactionInterface, NftTransactionInterface @@ -55,15 +54,13 @@ export type DynamicTransactionType = ? TransactionInterface : T extends TransactionTypeEnum.CONTRACT ? ContractTransactionInterface - : T extends TransactionTypeEnum.ASSET - ? AssetTransactionInterface - : T extends TransactionTypeEnum.COIN - ? CoinTransactionInterface - : T extends TransactionTypeEnum.TOKEN - ? TokenTransactionInterface - : T extends TransactionTypeEnum.NFT - ? NftTransactionInterface - : never + : T extends TransactionTypeEnum.COIN + ? CoinTransactionInterface + : T extends TransactionTypeEnum.TOKEN + ? TokenTransactionInterface + : T extends TransactionTypeEnum.NFT + ? NftTransactionInterface + : never /** * 'DynamicTransactionListenerFilterInterface' connects transaction types to their corresponding filter interfaces @@ -75,15 +72,13 @@ export type DynamicTransactionListenerFilterType ? TransactionListenerFilterInterface : T extends TransactionTypeEnum.CONTRACT ? ContractTransactionListenerFilterInterface - : T extends TransactionTypeEnum.ASSET - ? AssetTransactionListenerFilterInterface - : T extends TransactionTypeEnum.COIN - ? CoinTransactionListenerFilterInterface - : T extends TransactionTypeEnum.TOKEN - ? TokenTransactionListenerFilterInterface - : T extends TransactionTypeEnum.NFT - ? NftTransactionListenerFilterInterface - : never + : T extends TransactionTypeEnum.COIN + ? CoinTransactionListenerFilterInterface + : T extends TransactionTypeEnum.TOKEN + ? TokenTransactionListenerFilterInterface + : T extends TransactionTypeEnum.NFT + ? NftTransactionListenerFilterInterface + : never /** * 'TransactionListenerProcessIndex' is an object that connects transaction types to their corresponding process methods. @@ -92,7 +87,6 @@ export type DynamicTransactionListenerFilterType export const TransactionListenerProcessIndex = { [TransactionTypeEnum.GENERAL]: 'generalProcess', [TransactionTypeEnum.CONTRACT]: 'contractProcess', - [TransactionTypeEnum.ASSET]: 'assetProcess', [TransactionTypeEnum.COIN]: 'coinProcess', [TransactionTypeEnum.TOKEN]: 'tokenProcess', [TransactionTypeEnum.NFT]: 'nftProcess' @@ -148,8 +142,6 @@ export interface TransactionListenerInterface { contractProcess: () => void - assetProcess: () => void - coinProcess: () => void tokenProcess: () => void From 284f74603c6cb702d194dc1dce9e004de299fbc3 Mon Sep 17 00:00:00 2001 From: Halil Beycan <50718965+BeycanDeveloper@users.noreply.github.com> Date: Wed, 27 Mar 2024 20:28:00 +0800 Subject: [PATCH 034/114] updated --- packages/networks/boilerplate/package.json | 2 +- .../boilerplate/src/services/TransactionListener.ts | 7 ------- packages/networks/evm-chains/package.json | 2 +- packages/networks/evm-chains/pnpm-lock.yaml | 8 ++++---- .../evm-chains/src/services/TransactionListener.ts | 7 ------- 5 files changed, 6 insertions(+), 20 deletions(-) diff --git a/packages/networks/boilerplate/package.json b/packages/networks/boilerplate/package.json index 4b33230..e12e6b5 100644 --- a/packages/networks/boilerplate/package.json +++ b/packages/networks/boilerplate/package.json @@ -36,7 +36,7 @@ "url": "https://github.com/MultipleChain/js/issues" }, "dependencies": { - "@multiplechain/types": "^0.1.22", + "@multiplechain/types": "^0.1.23", "@multiplechain/utils": "^0.1.8" } } \ No newline at end of file diff --git a/packages/networks/boilerplate/src/services/TransactionListener.ts b/packages/networks/boilerplate/src/services/TransactionListener.ts index 5382093..1be059d 100644 --- a/packages/networks/boilerplate/src/services/TransactionListener.ts +++ b/packages/networks/boilerplate/src/services/TransactionListener.ts @@ -76,13 +76,6 @@ export class TransactionListener // Contract transaction process } - /** - * Asset transaction process - */ - assetProcess(): void { - // Asset transaction process - } - /** * Coin transaction process */ diff --git a/packages/networks/evm-chains/package.json b/packages/networks/evm-chains/package.json index 308c720..5f4e767 100644 --- a/packages/networks/evm-chains/package.json +++ b/packages/networks/evm-chains/package.json @@ -38,7 +38,7 @@ "url": "https://github.com/MultipleChain/js/issues" }, "dependencies": { - "@multiplechain/types": "^0.1.22", + "@multiplechain/types": "^0.1.23", "@multiplechain/utils": "^0.1.9" } } \ No newline at end of file diff --git a/packages/networks/evm-chains/pnpm-lock.yaml b/packages/networks/evm-chains/pnpm-lock.yaml index 3d6dd36..04a2499 100644 --- a/packages/networks/evm-chains/pnpm-lock.yaml +++ b/packages/networks/evm-chains/pnpm-lock.yaml @@ -6,16 +6,16 @@ settings: dependencies: '@multiplechain/types': - specifier: ^0.1.22 - version: 0.1.22 + specifier: ^0.1.23 + version: 0.1.23 '@multiplechain/utils': specifier: ^0.1.9 version: 0.1.9 packages: - /@multiplechain/types@0.1.22: - resolution: {integrity: sha512-0150RfkScgb+qDf5GFiAmFCsuIsQmjCUqvLv0n4JSUuhIkZA45NOwypo2UYOgBx6JiLyHLs4vqf9VUWaaUMTeA==} + /@multiplechain/types@0.1.23: + resolution: {integrity: sha512-P1PxaeQWoh2qSAr59h63vno9K0Y5WNrsgwLrAI5yXUPCZ+5RZQ1eU2m3CdStVWzHHqAJV3jZ8dw3pofx6myzlQ==} dev: false /@multiplechain/utils@0.1.9: diff --git a/packages/networks/evm-chains/src/services/TransactionListener.ts b/packages/networks/evm-chains/src/services/TransactionListener.ts index 5382093..1be059d 100644 --- a/packages/networks/evm-chains/src/services/TransactionListener.ts +++ b/packages/networks/evm-chains/src/services/TransactionListener.ts @@ -76,13 +76,6 @@ export class TransactionListener // Contract transaction process } - /** - * Asset transaction process - */ - assetProcess(): void { - // Asset transaction process - } - /** * Coin transaction process */ From 84fae15ee067e7a5c11923a18cdf93da0051f565 Mon Sep 17 00:00:00 2001 From: Halil Beycan <50718965+BeycanDeveloper@users.noreply.github.com> Date: Wed, 27 Mar 2024 20:59:01 +0800 Subject: [PATCH 035/114] revert getStatus method --- packages/networks/evm-chains/src/models/Transaction.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/packages/networks/evm-chains/src/models/Transaction.ts b/packages/networks/evm-chains/src/models/Transaction.ts index 201437a..e6a7d3a 100644 --- a/packages/networks/evm-chains/src/models/Transaction.ts +++ b/packages/networks/evm-chains/src/models/Transaction.ts @@ -124,8 +124,10 @@ export class Transaction implements TransactionInterface { */ async getStatus(): Promise { const data = await this.getData() - if (data?.response?.blockNumber !== null) { - if (data?.receipt.status === 1) { + if (data === null) { + return TransactionStatusEnum.PENDING + } else if (data.response.blockNumber !== null) { + if (data.receipt.status === 1) { return TransactionStatusEnum.CONFIRMED } else { return TransactionStatusEnum.FAILED From 855b001c47cbf017c8b06d1ed95e462969237176 Mon Sep 17 00:00:00 2001 From: Halil Beycan <50718965+BeycanDeveloper@users.noreply.github.com> Date: Sat, 30 Mar 2024 14:19:38 +0800 Subject: [PATCH 036/114] updated error types --- packages/networks/evm-chains/src/assets/Coin.ts | 6 +++--- packages/networks/evm-chains/src/assets/Token.ts | 4 ++-- packages/networks/evm-chains/src/models/Transaction.ts | 6 +++--- packages/networks/evm-chains/src/services/Provider.ts | 10 +++++++--- 4 files changed, 15 insertions(+), 11 deletions(-) diff --git a/packages/networks/evm-chains/src/assets/Coin.ts b/packages/networks/evm-chains/src/assets/Coin.ts index 838a36f..8d9f630 100644 --- a/packages/networks/evm-chains/src/assets/Coin.ts +++ b/packages/networks/evm-chains/src/assets/Coin.ts @@ -2,7 +2,7 @@ import { Provider } from '../services/Provider.ts' import { hexToNumber, numberToHex } from '@multiplechain/utils' import { TransactionSigner } from '../services/TransactionSigner.ts' import type { TransactionData } from '../services/TransactionSigner.ts' -import type { CoinInterface } from '@multiplechain/types' +import { ErrorTypeEnum, type CoinInterface } from '@multiplechain/types' export class Coin implements CoinInterface { /** @@ -45,11 +45,11 @@ export class Coin implements CoinInterface { */ async transfer(sender: string, receiver: string, amount: number): Promise { if (amount < 0) { - throw new Error('Invalid amount') + throw new Error(ErrorTypeEnum.INVALID_AMOUNT) } if (amount > (await this.getBalance(sender))) { - throw new Error('Insufficient balance') + throw new Error(ErrorTypeEnum.INSUFFICIENT_BALANCE) } const { network, ethers } = Provider.instance diff --git a/packages/networks/evm-chains/src/assets/Token.ts b/packages/networks/evm-chains/src/assets/Token.ts index d1750c7..bface03 100644 --- a/packages/networks/evm-chains/src/assets/Token.ts +++ b/packages/networks/evm-chains/src/assets/Token.ts @@ -59,13 +59,13 @@ export class Token extends Contract implements TokenInterface { */ async transfer(sender: string, receiver: string, amount: number): Promise { if (amount < 0) { - throw new Error('Invalid amount') + throw new Error(ErrorTypeEnum.INVALID_AMOUNT) } const [balance, decimals] = await Promise.all([this.getBalance(sender), this.getDecimals()]) if (amount > balance) { - throw new Error('Insufficient balance') + throw new Error(ErrorTypeEnum.INSUFFICIENT_BALANCE) } const { network, ethers } = Provider.instance diff --git a/packages/networks/evm-chains/src/models/Transaction.ts b/packages/networks/evm-chains/src/models/Transaction.ts index e6a7d3a..c051d9f 100644 --- a/packages/networks/evm-chains/src/models/Transaction.ts +++ b/packages/networks/evm-chains/src/models/Transaction.ts @@ -1,5 +1,5 @@ import { Provider } from '../services/Provider.ts' -import { TransactionStatusEnum } from '@multiplechain/types' +import { ErrorTypeEnum, TransactionStatusEnum } from '@multiplechain/types' import type { TransactionInterface } from '@multiplechain/types' import type { TransactionReceipt, TransactionResponse } from 'ethers' import type { Ethers } from '../services/Ethers.ts' @@ -42,9 +42,9 @@ export class Transaction implements TransactionInterface { } catch (error) { const e = error as Error if (String(e.message).includes('timeout')) { - throw new Error('RPC Timeout') + throw new Error(ErrorTypeEnum.RPC_TIMEOUT) } - throw new Error('Transaction not found') + throw new Error(ErrorTypeEnum.RPC_REQUEST_ERROR) } } diff --git a/packages/networks/evm-chains/src/services/Provider.ts b/packages/networks/evm-chains/src/services/Provider.ts index c38e38d..f4ac7b5 100644 --- a/packages/networks/evm-chains/src/services/Provider.ts +++ b/packages/networks/evm-chains/src/services/Provider.ts @@ -1,5 +1,9 @@ import { Ethers } from './Ethers.ts' -import type { NetworkConfigInterface, ProviderInterface } from '@multiplechain/types' +import { + ErrorTypeEnum, + type NetworkConfigInterface, + type ProviderInterface +} from '@multiplechain/types' export interface EvmNetworkConfigInterface extends NetworkConfigInterface { id: number @@ -46,7 +50,7 @@ export class Provider implements Omit { */ static get instance(): Provider { if (Provider._instance === undefined) { - throw new Error('Provider is not initialized') + throw new Error(ErrorTypeEnum.PROVIDER_IS_NOT_INITIALIZED) } return Provider._instance } @@ -57,7 +61,7 @@ export class Provider implements Omit { */ static initialize(network: EvmNetworkConfigInterface): void { if (Provider._instance !== undefined) { - throw new Error('Provider is already initialized') + throw new Error(ErrorTypeEnum.PROVIDER_IS_ALREADY_INITIALIZED) } Provider._instance = new Provider(network) } From 0e985d9371f259942501a982af2adc780df6a571 Mon Sep 17 00:00:00 2001 From: Halil Beycan <50718965+BeycanDeveloper@users.noreply.github.com> Date: Sat, 30 Mar 2024 17:51:17 +0800 Subject: [PATCH 037/114] transferFrom completed for token --- .../networks/evm-chains/src/assets/Token.ts | 74 +++++++++++++++---- .../evm-chains/src/models/Transaction.ts | 3 +- .../evm-chains/src/services/Ethers.ts | 7 ++ .../src/services/TransactionSigner.ts | 22 +++++- .../networks/evm-chains/tests/assets.spec.ts | 26 ++++++- 5 files changed, 107 insertions(+), 25 deletions(-) diff --git a/packages/networks/evm-chains/src/assets/Token.ts b/packages/networks/evm-chains/src/assets/Token.ts index bface03..0c0405d 100644 --- a/packages/networks/evm-chains/src/assets/Token.ts +++ b/packages/networks/evm-chains/src/assets/Token.ts @@ -37,8 +37,10 @@ export class Token extends Contract implements TokenInterface { * @returns Wallet balance as currency of TOKEN or COIN assets */ async getBalance(owner: string): Promise { - const decimals = await this.getDecimals() - const balance = await this.callMethod('balanceOf', owner) + const [decimals, balance] = await Promise.all([ + this.getDecimals(), + this.callMethod('balanceOf', owner) + ]) return hexToNumber(balance as string, decimals) } @@ -46,8 +48,10 @@ export class Token extends Contract implements TokenInterface { * @returns Total supply of the token */ async getTotalSupply(): Promise { - const decimals = await this.getDecimals() - const totalSupply = await this.callMethod('totalSupply') + const [decimals, totalSupply] = await Promise.all([ + this.getDecimals(), + this.callMethod('totalSupply') + ]) return hexToNumber(totalSupply as string, decimals) } @@ -62,7 +66,7 @@ export class Token extends Contract implements TokenInterface { throw new Error(ErrorTypeEnum.INVALID_AMOUNT) } - const [balance, decimals] = await Promise.all([this.getBalance(sender), this.getDecimals()]) + const balance = await this.getBalance(sender) if (amount > balance) { throw new Error(ErrorTypeEnum.INSUFFICIENT_BALANCE) @@ -70,7 +74,7 @@ export class Token extends Contract implements TokenInterface { const { network, ethers } = Provider.instance - const hexAmount = numberToHex(amount, decimals) + const hexAmount = numberToHex(amount, await this.getDecimals()) const [gasPrice, nonce, data, gasLimit] = await Promise.all([ ethers.getGasPrice(), ethers.getNonce(sender), @@ -91,10 +95,11 @@ export class Token extends Contract implements TokenInterface { } /** - * transferFrom() transfers tokens from sender to receiver using allowance - * @param sender Sender wallet address + * @param spender Address of the spender of transaction + * @param owner Sender wallet address * @param receiver Receiver wallet address - * @param amount Amount of assets that will be transferred + * @param amount Amount of tokens that will be transferred + * @returns {Promise} */ async transferFrom( spender: string, @@ -106,7 +111,43 @@ export class Token extends Contract implements TokenInterface { throw new Error(ErrorTypeEnum.INVALID_AMOUNT) } - // + const balance = await this.getBalance(owner) + + if (amount > balance) { + throw new Error(ErrorTypeEnum.INSUFFICIENT_BALANCE) + } + + const allowance = await this.allowance(owner, spender) + + if (allowance === 0) { + throw new Error(ErrorTypeEnum.UNAUTHORIZED_ADDRESS) + } + + if (amount > allowance) { + throw new Error(ErrorTypeEnum.INVALID_AMOUNT) + } + + const { network, ethers } = Provider.instance + + const hexAmount = numberToHex(amount, await this.getDecimals()) + + const [gasPrice, nonce, data, gasLimit] = await Promise.all([ + ethers.getGasPrice(), + ethers.getNonce(spender), + this.getMethodData('transferFrom', owner, receiver, hexAmount), + this.getMethodEstimateGas('transferFrom', spender, owner, receiver, hexAmount) + ]) + + return new TransactionSigner({ + data, + nonce, + gasPrice, + gasLimit, + value: '0x0', + from: spender, + chainId: network.id, + to: this.getAddress() + }) } /** @@ -120,14 +161,14 @@ export class Token extends Contract implements TokenInterface { throw new Error(ErrorTypeEnum.INVALID_AMOUNT) } - const [balance, decimals] = await Promise.all([this.getBalance(owner), this.getDecimals()]) + const balance = await this.getBalance(owner) if (amount > balance) { throw new Error(ErrorTypeEnum.INSUFFICIENT_BALANCE) } const { network, ethers } = Provider.instance - const hexAmount = numberToHex(amount, decimals) + const hexAmount = numberToHex(amount, await this.getDecimals()) const [gasPrice, nonce, data, gasLimit] = await Promise.all([ ethers.getGasPrice(), @@ -154,9 +195,10 @@ export class Token extends Contract implements TokenInterface { * @returns Amount of the tokens that is being used by spender */ async allowance(owner: string, spender: string): Promise { - return hexToNumber( - (await this.callMethod('allowance', owner, spender)) as string, - await this.getDecimals() - ) + const [decimals, allowance] = await Promise.all([ + this.getDecimals(), + await this.callMethod('allowance', owner, spender) + ]) + return hexToNumber(allowance as string, decimals) } } diff --git a/packages/networks/evm-chains/src/models/Transaction.ts b/packages/networks/evm-chains/src/models/Transaction.ts index c051d9f..7bca953 100644 --- a/packages/networks/evm-chains/src/models/Transaction.ts +++ b/packages/networks/evm-chains/src/models/Transaction.ts @@ -40,8 +40,7 @@ export class Transaction implements TransactionInterface { } return { response, receipt } } catch (error) { - const e = error as Error - if (String(e.message).includes('timeout')) { + if (error instanceof Error && String(error.message).includes('timeout')) { throw new Error(ErrorTypeEnum.RPC_TIMEOUT) } throw new Error(ErrorTypeEnum.RPC_REQUEST_ERROR) diff --git a/packages/networks/evm-chains/src/services/Ethers.ts b/packages/networks/evm-chains/src/services/Ethers.ts index 3123cd6..33abb4a 100644 --- a/packages/networks/evm-chains/src/services/Ethers.ts +++ b/packages/networks/evm-chains/src/services/Ethers.ts @@ -11,6 +11,13 @@ import { Wallet, Contract, ContractFactory, JsonRpcProvider, WebSocketProvider } import type { EvmNetworkConfigInterface } from './Provider.ts' import type { TransactionData } from '../services/TransactionSigner.ts' +export interface EthersError { + shortMessage: string + code: string + value: string + args: string +} + export class Ethers { network: EvmNetworkConfigInterface diff --git a/packages/networks/evm-chains/src/services/TransactionSigner.ts b/packages/networks/evm-chains/src/services/TransactionSigner.ts index 7d4558d..d90d055 100644 --- a/packages/networks/evm-chains/src/services/TransactionSigner.ts +++ b/packages/networks/evm-chains/src/services/TransactionSigner.ts @@ -1,6 +1,11 @@ +import type { EthersError } from './Ethers.ts' import { Provider } from '../services/Provider.ts' import type { TransactionRequest, Wallet, BigNumberish } from 'ethers' -import { TransactionTypeEnum, type TransactionSignerInterface } from '@multiplechain/types' +import { + ErrorTypeEnum, + TransactionTypeEnum, + type TransactionSignerInterface +} from '@multiplechain/types' // Transactions import { Transaction } from '../models/Transaction.ts' @@ -49,9 +54,18 @@ export class TransactionSigner implements TransactionSignerInterface { * @param privateKey - Transaction data */ public async sign(privateKey: string): Promise { - this.wallet = ethers.wallet(privateKey) - this.signedData = await this.wallet.signTransaction(this.rawData) - return this + try { + this.wallet = ethers.wallet(privateKey) + this.signedData = await this.wallet.signTransaction(this.rawData) + return this + } catch (error) { + const e = error as EthersError + if (e?.shortMessage.includes('transaction from address mismatch')) { + throw new Error(ErrorTypeEnum.INVALID_PRIVATE_KEY) + } + + throw error + } } /** diff --git a/packages/networks/evm-chains/tests/assets.spec.ts b/packages/networks/evm-chains/tests/assets.spec.ts index 644c20d..b4ed0be 100644 --- a/packages/networks/evm-chains/tests/assets.spec.ts +++ b/packages/networks/evm-chains/tests/assets.spec.ts @@ -16,21 +16,22 @@ const coinBalanceTestAmount = 0.01 const tokenBalanceTestAmount = 1000 const tokenApproveTestAmount = 100 -const walletPrivateKey = '0x14bd9af4e87981b37b7b2e8a0d1d249b7fcdb7a3bc579c4c31488842d372c0e9' +const senderPrivateKey = '0x14bd9af4e87981b37b7b2e8a0d1d249b7fcdb7a3bc579c4c31488842d372c0e9' +const receiverPrivateKey = '0x22ac1009c43f251e0b5a808751990abe77a74fe12f390c0cc95ab179a0b61a5a' const senderTestAddress = '0x110600bF0399174520a159ed425f0D272Ff8b459' const receiverTestAddress = '0xbBa4d06D1cEf94b35aDeCfDa893523907fdD36DE' const tokenTestAddress = '0x4294cb0dD25dC9140B5127f247cBd47Eeb673431' const transferTestAmount = 0.0001 const tokenTransferTestAmount = 1 -const checkSigner = async (signer: TransactionSigner): Promise => { +const checkSigner = async (signer: TransactionSigner, privateKey?: string): Promise => { expect(signer).toBeInstanceOf(TransactionSigner) const rawData = signer.getRawData() assert.isObject(rawData) - await signer.sign(walletPrivateKey) + await signer.sign(privateKey ?? senderPrivateKey) assert.isString(signer.getSignedData()) } @@ -149,6 +150,25 @@ describe('Token', () => { tokenApproveTestAmount ) }) + + it('Transfer from', async () => { + if (!transferTestIsOpen) return + const signer = await token.transferFrom( + receiverTestAddress, + senderTestAddress, + receiverTestAddress, + 2 + ) + + await checkSigner(signer, receiverPrivateKey) + + const beforeBalance = await token.getBalance(receiverTestAddress) + + await checkTx(await signer.send()) + + const afterBalance = await token.getBalance(receiverTestAddress) + expect(afterBalance).toBe(fixFloat(beforeBalance + 2)) + }) }) // describe('Nft', () => {}) From 4b8cc4f9d03a26315b30f13448cf5a35054879f1 Mon Sep 17 00:00:00 2001 From: Halil Beycan <50718965+BeycanDeveloper@users.noreply.github.com> Date: Sat, 30 Mar 2024 20:13:59 +0800 Subject: [PATCH 038/114] updated allowance to getAllowance --- packages/types/package.json | 2 +- packages/types/src/assets.ts | 26 +++++++++++++------------- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/packages/types/package.json b/packages/types/package.json index 8780b43..22ecb3d 100644 --- a/packages/types/package.json +++ b/packages/types/package.json @@ -1,6 +1,6 @@ { "name": "@multiplechain/types", - "version": "0.1.23", + "version": "0.1.24", "type": "module", "main": "./src/index.ts", "types": "./src/index.ts", diff --git a/packages/types/src/assets.ts b/packages/types/src/assets.ts index 6e2a449..6e6f751 100644 --- a/packages/types/src/assets.ts +++ b/packages/types/src/assets.ts @@ -94,6 +94,13 @@ export interface TokenInterface */ getTotalSupply: () => Promise + /** + * @param owner Address of owner of the tokens that is being used + * @param spender Address of the spender that is using the tokens of owner + * @returns Amount of the tokens that is being used by spender + */ + getAllowance: (owner: string, spender: string) => Promise + /** * @param spender Address of the spender of transaction * @param owner Sender wallet address @@ -115,13 +122,6 @@ export interface TokenInterface * @param amount Amount of the tokens that will be used */ approve: (owner: string, spender: string, amount: number) => Promise - - /** - * @param owner Address of owner of the tokens that is being used - * @param spender Address of the spender that is using the tokens of owner - * @returns Amount of the tokens that is being used by spender - */ - allowance: (owner: string, spender: string) => Promise } export interface NftInterface @@ -149,6 +149,12 @@ export interface NftInterface */ getTokenURI: (nftId: number) => Promise + /** + * @param nftId ID of the NFT that will be transferred + * @returns Amount of the tokens that is being used by spender + */ + getApproved: (nftId: number) => Promise + /** * Transfers an NFT * @param sender Sender wallet address @@ -182,10 +188,4 @@ export interface NftInterface * @param nftId ID of the NFT that will be transferred */ approve: (owner: string, spender: string, nftId: number) => Promise - - /** - * @param nftId ID of the NFT that will be transferred - * @returns Amount of the tokens that is being used by spender - */ - getApproved: (nftId: number) => Promise } From bef0f4f4f0578a5d799baee36bec07f2ff251fae Mon Sep 17 00:00:00 2001 From: Halil Beycan <50718965+BeycanDeveloper@users.noreply.github.com> Date: Sat, 30 Mar 2024 20:15:11 +0800 Subject: [PATCH 039/114] assets done --- packages/networks/evm-chains/package.json | 2 +- packages/networks/evm-chains/pnpm-lock.yaml | 8 +- .../networks/evm-chains/src/assets/NFT.ts | 105 ++++++++-------- .../networks/evm-chains/src/assets/Token.ts | 30 ++--- .../networks/evm-chains/tests/assets.spec.ts | 118 +++++++++++++++--- 5 files changed, 173 insertions(+), 90 deletions(-) diff --git a/packages/networks/evm-chains/package.json b/packages/networks/evm-chains/package.json index 5f4e767..403987e 100644 --- a/packages/networks/evm-chains/package.json +++ b/packages/networks/evm-chains/package.json @@ -38,7 +38,7 @@ "url": "https://github.com/MultipleChain/js/issues" }, "dependencies": { - "@multiplechain/types": "^0.1.23", + "@multiplechain/types": "^0.1.24", "@multiplechain/utils": "^0.1.9" } } \ No newline at end of file diff --git a/packages/networks/evm-chains/pnpm-lock.yaml b/packages/networks/evm-chains/pnpm-lock.yaml index 04a2499..d8d75f6 100644 --- a/packages/networks/evm-chains/pnpm-lock.yaml +++ b/packages/networks/evm-chains/pnpm-lock.yaml @@ -6,16 +6,16 @@ settings: dependencies: '@multiplechain/types': - specifier: ^0.1.23 - version: 0.1.23 + specifier: ^0.1.24 + version: 0.1.24 '@multiplechain/utils': specifier: ^0.1.9 version: 0.1.9 packages: - /@multiplechain/types@0.1.23: - resolution: {integrity: sha512-P1PxaeQWoh2qSAr59h63vno9K0Y5WNrsgwLrAI5yXUPCZ+5RZQ1eU2m3CdStVWzHHqAJV3jZ8dw3pofx6myzlQ==} + /@multiplechain/types@0.1.24: + resolution: {integrity: sha512-CsfAtGf/k88h0xU6yiJUeef4vj8NwFuBV5tmMk4Y27Fbcu4TbpigutDRwgbBSY9kZbv3EbrxcniUUFfPCTc7Ow==} dev: false /@multiplechain/utils@0.1.9: diff --git a/packages/networks/evm-chains/src/assets/NFT.ts b/packages/networks/evm-chains/src/assets/NFT.ts index 5ec6704..5dea597 100644 --- a/packages/networks/evm-chains/src/assets/NFT.ts +++ b/packages/networks/evm-chains/src/assets/NFT.ts @@ -28,7 +28,31 @@ export class NFT extends Contract implements NftInterface { * @returns Number of tokens of owner */ async getBalance(owner: string): Promise { - return await this.ethersContract.balanceOf(owner) + return Number(await this.callMethod('balanceOf', owner)) + } + + /** + * @param nftId NFT ID + * @returns NFT owner wallet address + */ + async getOwner(nftId: number): Promise { + return await this.callMethod('ownerOf', nftId) + } + + /** + * @param nftId NFT ID + * @returns NFT URI + */ + async getTokenURI(nftId: number): Promise { + return await this.callMethod('tokenURI', nftId) + } + + /** + * @param nftId ID of the NFT that will be transferred + * @returns Amount of the tokens that is being used by spender + */ + async getApproved(nftId: number): Promise { + return await this.callMethod('getApproved', nftId) } /** @@ -38,8 +62,17 @@ export class NFT extends Contract implements NftInterface { * @returns Transaction signer */ async transfer(sender: string, receiver: string, nftId: number): Promise { + return await this.transferFrom(sender, sender, receiver, nftId) + } + + async transferFrom( + spender: string, + owner: string, + receiver: string, + nftId: number + ): Promise { // Check if tokens exist - const balance = await this.getBalance(sender) + const balance = await this.getBalance(owner) if (balance <= 0) { throw new Error(ErrorTypeEnum.INSUFFICIENT_BALANCE) @@ -47,17 +80,25 @@ export class NFT extends Contract implements NftInterface { // Check ownership const originalOwner = await this.getOwner(nftId) - if (originalOwner !== sender) { + if (originalOwner !== owner) { throw new Error(ErrorTypeEnum.UNAUTHORIZED_ADDRESS) } + // check if spender different from owner + if (spender !== owner) { + const approved = await this.getApproved(nftId) + if (approved !== spender) { + throw new Error(ErrorTypeEnum.UNAUTHORIZED_ADDRESS) + } + } + const { network, ethers } = Provider.instance const [gasPrice, nonce, data, gasLimit] = await Promise.all([ ethers.getGasPrice(), - ethers.getNonce(sender), - this.getMethodData('transfer', receiver, nftId), - this.getMethodEstimateGas('transfer', sender, receiver, nftId) + ethers.getNonce(spender), + this.getMethodData('transferFrom', owner, receiver, nftId), + this.getMethodEstimateGas('transferFrom', spender, owner, receiver, nftId) ]) return new TransactionSigner({ @@ -66,50 +107,12 @@ export class NFT extends Contract implements NftInterface { gasPrice, gasLimit, value: '0x0', - from: sender, + from: spender, chainId: network.id, - to: receiver + to: this.getAddress() }) } - async transferFrom( - spender: string, - owner: string, - receiver: string, - nftId: number - ): Promise { - // Check if tokens exist - const balance = await this.getBalance(owner) - - if (balance <= 0) { - throw new Error(ErrorTypeEnum.INSUFFICIENT_BALANCE) - } - - // Check ownership - const originalOwner = await this.getOwner(nftId) - if (originalOwner !== owner) { - throw new Error(ErrorTypeEnum.UNAUTHORIZED_ADDRESS) - } - - // - } - - /** - * @param nftId NFT ID - * @returns NFT owner wallet address - */ - async getOwner(nftId: number): Promise { - return await this.ethersContract.ownerOf(nftId) - } - - /** - * @param nftId NFT ID - * @returns NFT URI - */ - async getTokenURI(nftId: number): Promise { - return await this.ethersContract.tokenURI(nftId) - } - /** * Gives permission to the spender to spend owner's tokens * @param owner Address of owner of the tokens that will be used @@ -147,15 +150,7 @@ export class NFT extends Contract implements NftInterface { value: '0x0', from: owner, chainId: network.id, - to: spender + to: this.getAddress() }) } - - /** - * @param nftId ID of the NFT that will be transferred - * @returns Amount of the tokens that is being used by spender - */ - async getApproved(nftId: number): Promise { - return await this.ethersContract.getApproved(nftId) - } } diff --git a/packages/networks/evm-chains/src/assets/Token.ts b/packages/networks/evm-chains/src/assets/Token.ts index 0c0405d..25bcd80 100644 --- a/packages/networks/evm-chains/src/assets/Token.ts +++ b/packages/networks/evm-chains/src/assets/Token.ts @@ -55,6 +55,19 @@ export class Token extends Contract implements TokenInterface { return hexToNumber(totalSupply as string, decimals) } + /** + * @param owner Address of owner of the tokens that is being used + * @param spender Address of the spender that is using the tokens of owner + * @returns Amount of the tokens that is being used by spender + */ + async getAllowance(owner: string, spender: string): Promise { + const [decimals, allowance] = await Promise.all([ + this.getDecimals(), + await this.callMethod('allowance', owner, spender) + ]) + return hexToNumber(allowance as string, decimals) + } + /** * transfer() method is the main method for processing transfers for fungible assets (TOKEN, COIN) * @param sender Sender wallet address @@ -62,7 +75,7 @@ export class Token extends Contract implements TokenInterface { * @param amount Amount of assets that will be transferred */ async transfer(sender: string, receiver: string, amount: number): Promise { - if (amount < 0) { + if (amount <= 0) { throw new Error(ErrorTypeEnum.INVALID_AMOUNT) } @@ -117,7 +130,7 @@ export class Token extends Contract implements TokenInterface { throw new Error(ErrorTypeEnum.INSUFFICIENT_BALANCE) } - const allowance = await this.allowance(owner, spender) + const allowance = await this.getAllowance(owner, spender) if (allowance === 0) { throw new Error(ErrorTypeEnum.UNAUTHORIZED_ADDRESS) @@ -188,17 +201,4 @@ export class Token extends Contract implements TokenInterface { to: this.getAddress() }) } - - /** - * @param owner Address of owner of the tokens that is being used - * @param spender Address of the spender that is using the tokens of owner - * @returns Amount of the tokens that is being used by spender - */ - async allowance(owner: string, spender: string): Promise { - const [decimals, allowance] = await Promise.all([ - this.getDecimals(), - await this.callMethod('allowance', owner, spender) - ]) - return hexToNumber(allowance as string, decimals) - } } diff --git a/packages/networks/evm-chains/tests/assets.spec.ts b/packages/networks/evm-chains/tests/assets.spec.ts index b4ed0be..f8a450f 100644 --- a/packages/networks/evm-chains/tests/assets.spec.ts +++ b/packages/networks/evm-chains/tests/assets.spec.ts @@ -1,6 +1,7 @@ import { describe, it, expect, assert } from 'vitest' import ERC20 from '../resources/erc20.json' +import { NFT } from '../src/assets/NFT.ts' import { Coin } from '../src/assets/Coin.ts' import { Token } from '../src/assets/Token.ts' import { numberToHex, fixFloat } from '@multiplechain/utils' @@ -9,20 +10,31 @@ import { Transaction } from '../src/models/Transaction.ts' import { TransactionStatusEnum } from '@multiplechain/types' import { TransactionSigner } from '../src/services/TransactionSigner.ts' -const transferTestIsOpen = false +const coinTransferTestIsActive = false +const tokenTransferTestIsActive = false +const tokenApproveTestIsActive = false +const tokenTransferFromTestIsActive = false +const nftTransactionTestIsActive = false const balanceTestAddress = '0x760A4d3D03928D1e8541A7644B34370c1b79aa9F' const coinBalanceTestAmount = 0.01 const tokenBalanceTestAmount = 1000 -const tokenApproveTestAmount = 100 +const nftBalanceTestAmount = 2 const senderPrivateKey = '0x14bd9af4e87981b37b7b2e8a0d1d249b7fcdb7a3bc579c4c31488842d372c0e9' const receiverPrivateKey = '0x22ac1009c43f251e0b5a808751990abe77a74fe12f390c0cc95ab179a0b61a5a' const senderTestAddress = '0x110600bF0399174520a159ed425f0D272Ff8b459' const receiverTestAddress = '0xbBa4d06D1cEf94b35aDeCfDa893523907fdD36DE' const tokenTestAddress = '0x4294cb0dD25dC9140B5127f247cBd47Eeb673431' +const nftTestAddress = '0x06B8B36e4feD2206E980445C0f0829fc6B2aA91F' const transferTestAmount = 0.0001 const tokenTransferTestAmount = 1 +const tokenApproveTestAmount = 100 +const nftTransferId = 7 + +const waitSecondsBeforeThanNewTx = async (seconds: number): Promise => { + return await new Promise((resolve) => setTimeout(resolve, seconds * 1000)) +} const checkSigner = async (signer: TransactionSigner, privateKey?: string): Promise => { expect(signer).toBeInstanceOf(TransactionSigner) @@ -38,7 +50,7 @@ const checkSigner = async (signer: TransactionSigner, privateKey?: string): Prom const checkTx = async (transaction: Transaction): Promise => { expect(transaction).toBeInstanceOf(Transaction) - const status = await transaction.wait() + const status = await transaction.wait(10) expect(status).toBe(TransactionStatusEnum.CONFIRMED) } @@ -59,7 +71,8 @@ describe('Coin', () => { }) it('Transfer', async () => { - if (!transferTestIsOpen) return + if (!coinTransferTestIsActive) return + const signer = await coin.transfer( senderTestAddress, receiverTestAddress, @@ -78,13 +91,8 @@ describe('Coin', () => { }) describe('Contract', () => { - const contract = new Contract(tokenTestAddress, ERC20) - it('callMethod', async () => { - const name = await contract.callMethod('name') - expect(name).toBe('MyToken') - }) - it('getMethodData', async () => { + const contract = new Contract(tokenTestAddress, ERC20) const decimals = await contract.callMethod('decimals') const hexAmount = numberToHex(tokenBalanceTestAmount, Number(decimals)) const data = await contract.getMethodData('transfer', receiverTestAddress, hexAmount) @@ -117,7 +125,10 @@ describe('Token', () => { }) it('Transfer', async () => { - if (!transferTestIsOpen) return + if (!tokenTransferTestIsActive) return + + await waitSecondsBeforeThanNewTx(30) + const signer = await token.transfer( senderTestAddress, receiverTestAddress, @@ -135,7 +146,10 @@ describe('Token', () => { }) it('Approve and Allowance', async () => { - if (!transferTestIsOpen) return + if (!tokenApproveTestIsActive) return + + await waitSecondsBeforeThanNewTx(30) + const signer = await token.approve( senderTestAddress, receiverTestAddress, @@ -146,13 +160,16 @@ describe('Token', () => { await checkTx(await signer.send()) - expect(await token.allowance(senderTestAddress, receiverTestAddress)).toBe( + expect(await token.getAllowance(senderTestAddress, receiverTestAddress)).toBe( tokenApproveTestAmount ) }) it('Transfer from', async () => { - if (!transferTestIsOpen) return + if (!tokenTransferFromTestIsActive) return + + await waitSecondsBeforeThanNewTx(30) + const signer = await token.transferFrom( receiverTestAddress, senderTestAddress, @@ -171,4 +188,75 @@ describe('Token', () => { }) }) -// describe('Nft', () => {}) +describe('Nft', () => { + const nft = new NFT(nftTestAddress) + + it('Name and symbol', async () => { + expect(await nft.getName()).toBe('TestNFT') + expect(await nft.getSymbol()).toBe('TNFT') + }) + + it('Balance', async () => { + const balance = await nft.getBalance(balanceTestAddress) + expect(balance).toBe(nftBalanceTestAmount) + }) + + it('Owner', async () => { + expect(await nft.getOwner(5)).toBe(balanceTestAddress) + }) + + it('Token URI', async () => { + expect(await nft.getTokenURI(5)).toBe('') + }) + + it('Approved', async () => { + expect(await nft.getApproved(5)).toBe('0x0000000000000000000000000000000000000000') + }) + + it('Transfer', async () => { + if (!nftTransactionTestIsActive) return + + await waitSecondsBeforeThanNewTx(30) + + const signer = await nft.transfer(senderTestAddress, receiverTestAddress, nftTransferId) + + await checkSigner(signer) + + await checkTx(await signer.send()) + + expect(await nft.getOwner(nftTransferId)).toBe(receiverTestAddress) + }) + + it('Approve', async () => { + if (!nftTransactionTestIsActive) return + + await waitSecondsBeforeThanNewTx(30) + + const signer = await nft.approve(receiverTestAddress, senderTestAddress, nftTransferId) + + await checkSigner(signer, receiverPrivateKey) + + await checkTx(await signer.send()) + + expect(await nft.getApproved(nftTransferId)).toBe(senderTestAddress) + }) + + it('Transfer from', async () => { + if (!nftTransactionTestIsActive) return + + await waitSecondsBeforeThanNewTx(30) + + const signer = await nft.transferFrom( + senderTestAddress, + receiverTestAddress, + senderTestAddress, + nftTransferId + ) + + await checkSigner(signer) + + await checkTx(await signer.send()) + + expect(await nft.getOwner(nftTransferId)).toBe(senderTestAddress) + }) +}) From 8533a383d3533b3a4d168357d9a8d76ae5adc91e Mon Sep 17 00:00:00 2001 From: Halil Beycan <50718965+BeycanDeveloper@users.noreply.github.com> Date: Sat, 30 Mar 2024 20:23:45 +0800 Subject: [PATCH 040/114] updated --- packages/networks/boilerplate/package.json | 2 +- packages/networks/boilerplate/pnpm-lock.yaml | 16 +++--- .../networks/boilerplate/src/assets/Coin.ts | 2 +- .../networks/boilerplate/src/assets/NFT.ts | 49 +++++++++++++++---- .../networks/boilerplate/src/assets/Token.ts | 34 +++++++++---- .../boilerplate/src/models/NftTransaction.ts | 14 ++++++ .../boilerplate/src/models/Transaction.ts | 4 ++ 7 files changed, 93 insertions(+), 28 deletions(-) diff --git a/packages/networks/boilerplate/package.json b/packages/networks/boilerplate/package.json index e12e6b5..f7eb6ef 100644 --- a/packages/networks/boilerplate/package.json +++ b/packages/networks/boilerplate/package.json @@ -36,7 +36,7 @@ "url": "https://github.com/MultipleChain/js/issues" }, "dependencies": { - "@multiplechain/types": "^0.1.23", + "@multiplechain/types": "^0.1.24", "@multiplechain/utils": "^0.1.8" } } \ No newline at end of file diff --git a/packages/networks/boilerplate/pnpm-lock.yaml b/packages/networks/boilerplate/pnpm-lock.yaml index e032632..beee03e 100644 --- a/packages/networks/boilerplate/pnpm-lock.yaml +++ b/packages/networks/boilerplate/pnpm-lock.yaml @@ -6,20 +6,20 @@ settings: dependencies: '@multiplechain/types': - specifier: ^0.1.13 - version: 0.1.15 + specifier: ^0.1.24 + version: 0.1.24 '@multiplechain/utils': - specifier: ^0.1.7 - version: 0.1.7 + specifier: ^0.1.8 + version: 0.1.9 packages: - /@multiplechain/types@0.1.15: - resolution: {integrity: sha512-BwXCEUHob1yxjca9AklG546EZeE5DNPRmXdKr1i4bFeWSb4jXDVKWw+KwJcusDTiFUufja8XqsM43I7tFpDCIg==} + /@multiplechain/types@0.1.24: + resolution: {integrity: sha512-CsfAtGf/k88h0xU6yiJUeef4vj8NwFuBV5tmMk4Y27Fbcu4TbpigutDRwgbBSY9kZbv3EbrxcniUUFfPCTc7Ow==} dev: false - /@multiplechain/utils@0.1.7: - resolution: {integrity: sha512-I29JEiL+OTs6I6Lb4dTSsshcODttgO8oeCIP0xvJnkebIHz8ODyNG6rnQtUV/cOHhf4S12ZBkLN4FNJFuy/Mmw==} + /@multiplechain/utils@0.1.9: + resolution: {integrity: sha512-52yrmloGDwXrMwOSfEiPJfePPIDeEqGMTE4u5QE2BQPdGe0Bto908pX4IIF1j0Srmv5TJdH9JN3MFEgzgo3qAw==} dependencies: bignumber.js: 9.1.2 web3-utils: 4.2.1 diff --git a/packages/networks/boilerplate/src/assets/Coin.ts b/packages/networks/boilerplate/src/assets/Coin.ts index 11dae68..1cb667e 100644 --- a/packages/networks/boilerplate/src/assets/Coin.ts +++ b/packages/networks/boilerplate/src/assets/Coin.ts @@ -19,7 +19,7 @@ export class Coin implements CoinInterface { /** * @returns Decimal value of the coin */ - async getDecimals(): Promise { + getDecimals(): number { return 18 } diff --git a/packages/networks/boilerplate/src/assets/NFT.ts b/packages/networks/boilerplate/src/assets/NFT.ts index 500989a..7d800cc 100644 --- a/packages/networks/boilerplate/src/assets/NFT.ts +++ b/packages/networks/boilerplate/src/assets/NFT.ts @@ -26,10 +26,27 @@ export class NFT extends Contract implements NftInterface { } /** - * @returns NFT ID + * @param nftId NFT ID + * @returns NFT owner wallet address */ - async getNftId(): Promise { - return 0 + async getOwner(nftId: number): Promise { + return 'example' + } + + /** + * @param nftId NFT ID + * @returns NFT URI + */ + async getTokenURI(nftId: number): Promise { + return 'example' + } + + /** + * @param nftId NFT ID + * @returns NFT URI + */ + async getApproved(nftId: number): Promise { + return 'example' } /** @@ -47,18 +64,32 @@ export class NFT extends Contract implements NftInterface { } /** + * @param spender Spender address + * @param sender Sender address + * @param receiver Receiver address * @param nftId NFT ID - * @returns NFT owner wallet address + * @returns Transaction signer */ - async getOwner(nftId: number): Promise { - return 'example' + async transferFrom( + spender: string, + owner: string, + receiver: string, + nftId: number + ): Promise { + return new TransactionSigner('example') } /** + * @param owner Owner of the nft + * @param spender Approved spender * @param nftId NFT ID - * @returns NFT URI + * @returns Transaction signer */ - async getTokenURI(nftId: number): Promise { - return 'example' + async approve( + owner: string, + spender: string, + nftId: number + ): Promise { + return new TransactionSigner('example') } } diff --git a/packages/networks/boilerplate/src/assets/Token.ts b/packages/networks/boilerplate/src/assets/Token.ts index 8b4acea..b59f152 100644 --- a/packages/networks/boilerplate/src/assets/Token.ts +++ b/packages/networks/boilerplate/src/assets/Token.ts @@ -39,6 +39,15 @@ export class Token extends Contract implements TokenInterface { return 0 } + /** + * @param owner Address of owner of the tokens that is being used + * @param spender Address of the spender that is using the tokens of owner + * @returns Amount of the tokens that is being used by spender + */ + async getAllowance(owner: string, spender: string): Promise { + return 0 + } + /** * transfer() method is the main method for processing transfers for fungible assets (TOKEN, COIN) * @param sender Sender wallet address @@ -53,6 +62,22 @@ export class Token extends Contract implements TokenInterface { return new TransactionSigner('example') } + /** + * @param spender Address of the spender of transaction + * @param owner Sender wallet address + * @param receiver Receiver wallet address + * @param amount Amount of tokens that will be transferred + * @override transfer() in AssetInterface + */ + async transferFrom( + spender: string, + owner: string, + receiver: string, + amount: number + ): Promise { + return new TransactionSigner('example') + } + /** * Gives permission to the spender to spend owner's tokens * @param owner Address of owner of the tokens that will be used @@ -66,13 +91,4 @@ export class Token extends Contract implements TokenInterface { ): Promise { return new TransactionSigner('example') } - - /** - * @param owner Address of owner of the tokens that is being used - * @param spender Address of the spender that is using the tokens of owner - * @returns Amount of the tokens that is being used by spender - */ - async allowance(owner: string, spender: string): Promise { - return 0 - } } diff --git a/packages/networks/boilerplate/src/models/NftTransaction.ts b/packages/networks/boilerplate/src/models/NftTransaction.ts index 8dd9d6b..84bbb2d 100644 --- a/packages/networks/boilerplate/src/models/NftTransaction.ts +++ b/packages/networks/boilerplate/src/models/NftTransaction.ts @@ -44,4 +44,18 @@ export class NftTransaction extends ContractTransaction implements NftTransactio ): Promise { return TransactionStatusEnum.PENDING } + + /** + * @param direction - Direction of the transaction (nft) + * @param address - Wallet address of the owner or spender of the transaction, dependant on direction + * @param nftId ID of the NFT that will be approved + * @override verifyApprove() in AssetTransactionInterface + */ + async verifyApprove( + direction: AssetDirectionEnum, + address: string, + nftId: number + ): Promise { + return TransactionStatusEnum.PENDING + } } diff --git a/packages/networks/boilerplate/src/models/Transaction.ts b/packages/networks/boilerplate/src/models/Transaction.ts index cd4941c..9ae82b4 100644 --- a/packages/networks/boilerplate/src/models/Transaction.ts +++ b/packages/networks/boilerplate/src/models/Transaction.ts @@ -18,6 +18,10 @@ export class Transaction implements TransactionInterface { return {} } + async wait(): Promise { + return await Promise.resolve(TransactionStatusEnum.CONFIRMED) + } + /** * @returns Transaction id from the blockchain network * this can be different names like txid, hash, signature etc. From 009dfae8861e22dd3008e9b98cb674cc2c593f23 Mon Sep 17 00:00:00 2001 From: Halil Beycan <50718965+BeycanDeveloper@users.noreply.github.com> Date: Sat, 30 Mar 2024 21:28:12 +0800 Subject: [PATCH 041/114] transaction model done --- package.json | 4 -- packages/networks/evm-chains/package.json | 4 +- .../evm-chains/src/models/Transaction.ts | 49 ++++++++++++++++--- .../networks/evm-chains/tests/models.spec.ts | 38 ++++++++++++-- 4 files changed, 80 insertions(+), 15 deletions(-) diff --git a/package.json b/package.json index 8dc7497..2b86cd2 100644 --- a/package.json +++ b/package.json @@ -29,9 +29,5 @@ "vite": "^5.1.4", "vite-plugin-node-polyfills": "^0.21.0", "vitest": "^1.3.1" - }, - "dependencies": { - "abi-decoder": "^2.4.0", - "ethers": "^6.11.1" } } diff --git a/packages/networks/evm-chains/package.json b/packages/networks/evm-chains/package.json index 403987e..efe7c77 100644 --- a/packages/networks/evm-chains/package.json +++ b/packages/networks/evm-chains/package.json @@ -39,6 +39,8 @@ }, "dependencies": { "@multiplechain/types": "^0.1.24", - "@multiplechain/utils": "^0.1.9" + "@multiplechain/utils": "^0.1.9", + "abi-decoder": "^2.4.0", + "ethers": "^6.11.1" } } \ No newline at end of file diff --git a/packages/networks/evm-chains/src/models/Transaction.ts b/packages/networks/evm-chains/src/models/Transaction.ts index 7bca953..63f3e70 100644 --- a/packages/networks/evm-chains/src/models/Transaction.ts +++ b/packages/networks/evm-chains/src/models/Transaction.ts @@ -3,6 +3,7 @@ import { ErrorTypeEnum, TransactionStatusEnum } from '@multiplechain/types' import type { TransactionInterface } from '@multiplechain/types' import type { TransactionReceipt, TransactionResponse } from 'ethers' import type { Ethers } from '../services/Ethers.ts' +import { hexToNumber } from '@multiplechain/utils' interface TransactionData { response: TransactionResponse @@ -15,13 +16,27 @@ export class Transaction implements TransactionInterface { */ id: string + /** + * Blockchain network provider + */ + provider: Provider + /** * Ethers service */ ethers: Ethers + /** + * Transaction data after completed + */ + data: TransactionData + + /** + * @param id Transaction ID + */ constructor(id: string) { this.id = id + this.provider = Provider.instance this.ethers = Provider.instance.ethers } @@ -29,6 +44,9 @@ export class Transaction implements TransactionInterface { * @returns Raw transaction data that is taken by blockchain network via RPC. */ async getData(): Promise { + if (this.data !== undefined) { + return this.data + } try { const response = await this.ethers.getTransaction(this.id) if (response === null) { @@ -38,7 +56,7 @@ export class Transaction implements TransactionInterface { if (receipt === null) { return null } - return { response, receipt } + return (this.data = { response, receipt }) } catch (error) { if (error instanceof Error && String(error.message).includes('timeout')) { throw new Error(ErrorTypeEnum.RPC_TIMEOUT) @@ -80,42 +98,59 @@ export class Transaction implements TransactionInterface { * @returns Blockchain explorer URL of the transaction. Dependant on network. */ getUrl(): string { - return 'example' + let explorerUrl = this.provider.network.explorerUrl + explorerUrl += explorerUrl.endsWith('/') ? '' : '/' + explorerUrl += 'tx/' + this.id + return explorerUrl } /** * @returns Wallet address of the sender of transaction */ async getSender(): Promise { - return 'example' + const data = await this.getData() + return data?.response.from ?? '' } /** * @returns Transaction fee as native coin amount */ async getFee(): Promise { - return 0 + const data = await this.getData() + if (data === null) { + return 0 + } + return hexToNumber( + (data?.response.gasPrice * data?.receipt.gasUsed).toString(), + this.provider.network.nativeCurrency.decimals + ) } /** * @returns Block ID of the transaction */ async getBlockNumber(): Promise { - return 0 + const data = await this.getData() + return data?.response.blockNumber ?? 0 } /** * @returns UNIX timestamp of the date that block is added to blockchain */ async getBlockTimestamp(): Promise { - return 0 + const blockNumber = await this.getBlockNumber() + const block = await this.ethers.getBlock(blockNumber) + return block?.timestamp ?? 0 } /** * @returns Confirmation count of the block that transaction is included */ async getBlockConfirmationCount(): Promise { - return 0 + const blockNumber = await this.getBlockNumber() + const blockCount = await this.ethers.getBlockNumber() + const confirmations = blockCount - blockNumber + return confirmations < 0 ? 0 : confirmations } /** diff --git a/packages/networks/evm-chains/tests/models.spec.ts b/packages/networks/evm-chains/tests/models.spec.ts index 7d82624..603787f 100644 --- a/packages/networks/evm-chains/tests/models.spec.ts +++ b/packages/networks/evm-chains/tests/models.spec.ts @@ -1,16 +1,48 @@ import { describe, it, expect } from 'vitest' import { Transaction } from '../src/models/Transaction.ts' +import { TransactionStatusEnum } from '@multiplechain/types' const txId = '0x566002399664e92f82ed654c181095bdd7ff3d3f1921d963257585891f622251' -describe('Tests for models', () => { +describe('Transaction', () => { const tx = new Transaction(txId) - it('Transaction Id', async () => { + it('Id', async () => { expect(tx.getId()).toBe(txId) }) - it('Transaction Data', async () => { + it('Data', async () => { expect(await tx.getData()).toBeTypeOf('object') }) + + it('URL', async () => { + expect(tx.getUrl()).toBe( + 'https://sepolia.etherscan.io/tx/0x566002399664e92f82ed654c181095bdd7ff3d3f1921d963257585891f622251' + ) + }) + + it('Sender', async () => { + expect(await tx.getSender()).toBe('0x74dBE9cA4F93087A27f23164d4367b8ce66C33e2') + }) + + it('Fee', async () => { + expect(await tx.getFee()).toBe(0.000371822357865) + }) + + it('Block Number', async () => { + expect(await tx.getBlockNumber()).toBe(5461884) + }) + + // Not give any response in vitest environment + // it('Block Timestamp', async () => { + // expect(await tx.getBlockTimestamp()).toBe(1710141144) + // }) + + it('Block Confirmation Count', async () => { + expect(await tx.getBlockConfirmationCount()).toBeGreaterThan(129954) + }) + + it('Status', async () => { + expect(await tx.getStatus()).toBe(TransactionStatusEnum.CONFIRMED) + }) }) From e58b86fb57eb6463811ff000c41f148aad56b1d9 Mon Sep 17 00:00:00 2001 From: Halil Beycan <50718965+BeycanDeveloper@users.noreply.github.com> Date: Sat, 30 Mar 2024 23:05:59 +0800 Subject: [PATCH 042/114] done ContractTransaction --- packages/networks/evm-chains/package.json | 1 - packages/networks/evm-chains/pnpm-lock.yaml | 86 ++++++++++++++++--- .../src/models/ContractTransaction.ts | 23 ++++- .../networks/evm-chains/tests/models.spec.ts | 24 +++++- 4 files changed, 117 insertions(+), 17 deletions(-) diff --git a/packages/networks/evm-chains/package.json b/packages/networks/evm-chains/package.json index efe7c77..b581acd 100644 --- a/packages/networks/evm-chains/package.json +++ b/packages/networks/evm-chains/package.json @@ -40,7 +40,6 @@ "dependencies": { "@multiplechain/types": "^0.1.24", "@multiplechain/utils": "^0.1.9", - "abi-decoder": "^2.4.0", "ethers": "^6.11.1" } } \ No newline at end of file diff --git a/packages/networks/evm-chains/pnpm-lock.yaml b/packages/networks/evm-chains/pnpm-lock.yaml index d8d75f6..67de6c2 100644 --- a/packages/networks/evm-chains/pnpm-lock.yaml +++ b/packages/networks/evm-chains/pnpm-lock.yaml @@ -11,9 +11,16 @@ dependencies: '@multiplechain/utils': specifier: ^0.1.9 version: 0.1.9 + ethers: + specifier: ^6.11.1 + version: 6.11.1 packages: + /@adraffy/ens-normalize@1.10.1: + resolution: {integrity: sha512-96Z2IP3mYmF1Xg2cDm8f1gWGf/HUVedQ3FMifV4kG/PQ4yEP51xDtRAEfhVNt5f/uzpNkZHwWQuUcu6D6K+Ekw==} + dev: false + /@multiplechain/types@0.1.24: resolution: {integrity: sha512-CsfAtGf/k88h0xU6yiJUeef4vj8NwFuBV5tmMk4Y27Fbcu4TbpigutDRwgbBSY9kZbv3EbrxcniUUFfPCTc7Ow==} dev: false @@ -22,7 +29,13 @@ packages: resolution: {integrity: sha512-52yrmloGDwXrMwOSfEiPJfePPIDeEqGMTE4u5QE2BQPdGe0Bto908pX4IIF1j0Srmv5TJdH9JN3MFEgzgo3qAw==} dependencies: bignumber.js: 9.1.2 - web3-utils: 4.2.0 + web3-utils: 4.2.2 + dev: false + + /@noble/curves@1.2.0: + resolution: {integrity: sha512-oYclrNgRaM9SsBUBVbb8M6DTV7ZHRTKugureoYEncY5c65HOmRzvSiTE3y5CYaPYJA/GVkrhXEoF0M3Ya9PMnw==} + dependencies: + '@noble/hashes': 1.3.2 dev: false /@noble/curves@1.3.0: @@ -31,6 +44,11 @@ packages: '@noble/hashes': 1.3.3 dev: false + /@noble/hashes@1.3.2: + resolution: {integrity: sha512-MVC8EAQp7MvEcm30KWENFjgR+Mkmf+D189XJTkFIlwohU5hcBbn1ZkKq7KVTi2Hme3PMGF390DaL52beVrIihQ==} + engines: {node: '>= 16'} + dev: false + /@noble/hashes@1.3.3: resolution: {integrity: sha512-V7/fPHgl+jsVPXqqeOzT8egNj2iBIVt+ECeMMG8TdcnTikP3oaBtUVqpT/gYCR68aEBJSF+XbYUxStjbFMqIIA==} engines: {node: '>= 16'} @@ -55,6 +73,14 @@ packages: '@scure/base': 1.1.5 dev: false + /@types/node@18.15.13: + resolution: {integrity: sha512-N+0kuo9KgrUQ1Sn/ifDXsvg0TTleP7rIy4zOBGECxAljqvqfqpTfzx0Q1NUedOixRMBfe2Whhb056a42cWs26Q==} + dev: false + + /aes-js@4.0.0-beta.5: + resolution: {integrity: sha512-G965FqalsNyrPqgEGON7nIx1e/OVENSgiEIzyC63haUMuvNnwIgIjMs52hlTCKhkBny7A2ORNlfY9Zu+jmGk1Q==} + dev: false + /available-typed-arrays@1.0.7: resolution: {integrity: sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==} engines: {node: '>= 0.4'} @@ -107,6 +133,26 @@ packages: '@scure/bip39': 1.2.2 dev: false + /ethers@6.11.1: + resolution: {integrity: sha512-mxTAE6wqJQAbp5QAe/+o+rXOID7Nw91OZXvgpjDa1r4fAbq2Nu314oEZSbjoRLacuCzs7kUC3clEvkCQowffGg==} + engines: {node: '>=14.0.0'} + dependencies: + '@adraffy/ens-normalize': 1.10.1 + '@noble/curves': 1.2.0 + '@noble/hashes': 1.3.2 + '@types/node': 18.15.13 + aes-js: 4.0.0-beta.5 + tslib: 2.4.0 + ws: 8.5.0 + transitivePeerDependencies: + - bufferutil + - utf-8-validate + dev: false + + /eventemitter3@5.0.1: + resolution: {integrity: sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==} + dev: false + /for-each@0.3.3: resolution: {integrity: sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==} dependencies: @@ -212,6 +258,10 @@ packages: has-property-descriptors: 1.0.2 dev: false + /tslib@2.4.0: + resolution: {integrity: sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==} + dev: false + /util@0.12.5: resolution: {integrity: sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA==} dependencies: @@ -226,32 +276,33 @@ packages: resolution: {integrity: sha512-WahtszSqILez+83AxGecVroyZsMuuRT+KmQp4Si5P4Rnqbczno1k748PCrZTS1J4UCPmXMG2/Vt+0Bz2zwXkwQ==} engines: {node: '>=14', npm: '>=6.12.0'} dependencies: - web3-types: 1.4.0 + web3-types: 1.5.0 dev: false - /web3-types@1.4.0: - resolution: {integrity: sha512-QnGDNredYqtZ49YD1pIPhsQTJJTOnYPCOnvrUs4/3XzeQLuDM+bAJ8fZ6U2nGEV77h81z2Ins6RE/f40yltvww==} + /web3-types@1.5.0: + resolution: {integrity: sha512-geWuMIeegQ8AedKAO6wO4G4j1gyQ1F/AyKLMw2vud4bsfZayyzWJgCMDZtjYMm5uo2a7i8j1W3/4QFmzlSy5cw==} engines: {node: '>=14', npm: '>=6.12.0'} dev: false - /web3-utils@4.2.0: - resolution: {integrity: sha512-UE7tmqPnC6sD0kpHhZiO9Zu8q7hiBItCQhnmxoMxk8OI91qlBWw6L7w1VNZo7TMBWH1Qe4R5l8h2vaoQCizVyA==} + /web3-utils@4.2.2: + resolution: {integrity: sha512-z+4owWcnoB4EH8yWIL1FBeyqe+sXwaGxUDtVTNPTMf2oB5C+paCToZUdCV5Bi+M543zZEzlzNTabOD+OWNc7NA==} engines: {node: '>=14', npm: '>=6.12.0'} dependencies: ethereum-cryptography: 2.1.3 + eventemitter3: 5.0.1 web3-errors: 1.1.4 - web3-types: 1.4.0 - web3-validator: 2.0.4 + web3-types: 1.5.0 + web3-validator: 2.0.5 dev: false - /web3-validator@2.0.4: - resolution: {integrity: sha512-qRxVePwdW+SByOmTpDZFWHIUAa7PswvxNszrOua6BoGqAhERo5oJZBN+EbWtK/+O+ApNxt5FR3nCPmiZldiOQA==} + /web3-validator@2.0.5: + resolution: {integrity: sha512-2gLOSW8XqEN5pw5jVUm20EB7A8SbQiekpAtiI0JBmCIV0a2rp97v8FgWY5E3UEqnw5WFfEqvcDVW92EyynDTyQ==} engines: {node: '>=14', npm: '>=6.12.0'} dependencies: ethereum-cryptography: 2.1.3 util: 0.12.5 web3-errors: 1.1.4 - web3-types: 1.4.0 + web3-types: 1.5.0 zod: 3.22.4 dev: false @@ -266,6 +317,19 @@ packages: has-tostringtag: 1.0.2 dev: false + /ws@8.5.0: + resolution: {integrity: sha512-BWX0SWVgLPzYwF8lTzEy1egjhS4S4OEAHfsO8o65WOVsrnSRGaSiUaa9e0ggGlkMTtBlmOpEXiie9RUcBO86qg==} + engines: {node: '>=10.0.0'} + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: ^5.0.2 + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + dev: false + /zod@3.22.4: resolution: {integrity: sha512-iC+8Io04lddc+mVqQ9AZ7OQ2MrUKGN+oIQyq1vemgt46jwCwLfhq7/pwnBnNXXXZb8VTVLKwp9EDkx+ryxIWmg==} dev: false diff --git a/packages/networks/evm-chains/src/models/ContractTransaction.ts b/packages/networks/evm-chains/src/models/ContractTransaction.ts index cb6f829..f09585c 100644 --- a/packages/networks/evm-chains/src/models/ContractTransaction.ts +++ b/packages/networks/evm-chains/src/models/ContractTransaction.ts @@ -1,8 +1,27 @@ import { Transaction } from './Transaction.ts' +import { Interface, type TransactionDescription } from 'ethers' import type { ContractTransactionInterface } from '@multiplechain/types' export class ContractTransaction extends Transaction implements ContractTransactionInterface { - getAddress(): string { - return 'example' + /** + * @returns {Promise} + */ + async getAddress(): Promise { + const data = await this.getData() + return data?.response.to ?? '' + } + + /** + * @param {object[]} abiArray + * @returns {Promise} + */ + async decodeData(abiArray: object[]): Promise { + const data = await this.getData() + if (data === null) return null + const iface = new Interface(abiArray) + return iface.parseTransaction({ + data: data?.response.data ?? '', + value: data?.response.value ?? 0 + }) } } diff --git a/packages/networks/evm-chains/tests/models.spec.ts b/packages/networks/evm-chains/tests/models.spec.ts index 603787f..41cbe40 100644 --- a/packages/networks/evm-chains/tests/models.spec.ts +++ b/packages/networks/evm-chains/tests/models.spec.ts @@ -1,14 +1,17 @@ import { describe, it, expect } from 'vitest' +import ERC20 from '../resources/erc20.json' import { Transaction } from '../src/models/Transaction.ts' import { TransactionStatusEnum } from '@multiplechain/types' +import { ContractTransaction } from '../src/models/ContractTransaction.ts' -const txId = '0x566002399664e92f82ed654c181095bdd7ff3d3f1921d963257585891f622251' +const etherTransferTx = '0x566002399664e92f82ed654c181095bdd7ff3d3f1921d963257585891f622251' +const tokenTransferTx = '0xdabda3905e585db91768f2ef877f7fbef7c0e8612c0a09c7b379981bdbc48975' describe('Transaction', () => { - const tx = new Transaction(txId) + const tx = new Transaction(etherTransferTx) it('Id', async () => { - expect(tx.getId()).toBe(txId) + expect(tx.getId()).toBe(etherTransferTx) }) it('Data', async () => { @@ -46,3 +49,18 @@ describe('Transaction', () => { expect(await tx.getStatus()).toBe(TransactionStatusEnum.CONFIRMED) }) }) + +describe('Contract Transaction', () => { + const tx = new ContractTransaction(tokenTransferTx) + + it('Address', async () => { + expect((await tx.getAddress()).toLowerCase()).toBe( + '0x4294cb0dD25dC9140B5127f247cBd47Eeb673431'.toLowerCase() + ) + }) + + it('Decode Data', async () => { + const result = await tx.decodeData(ERC20) + expect(result?.args[0]).toBe('0xbBa4d06D1cEf94b35aDeCfDa893523907fdD36DE') + }) +}) From 1cf29f5e97ab426e615a1421a94d9d188d3b9d9a Mon Sep 17 00:00:00 2001 From: Halil Beycan <50718965+BeycanDeveloper@users.noreply.github.com> Date: Sat, 30 Mar 2024 23:27:50 +0800 Subject: [PATCH 043/114] done CoinTransaction --- .../evm-chains/src/models/CoinTransaction.ts | 41 ++++++++++++++---- .../networks/evm-chains/tests/models.spec.ts | 43 ++++++++++++++++++- 2 files changed, 75 insertions(+), 9 deletions(-) diff --git a/packages/networks/evm-chains/src/models/CoinTransaction.ts b/packages/networks/evm-chains/src/models/CoinTransaction.ts index e8e2fa8..392fc78 100644 --- a/packages/networks/evm-chains/src/models/CoinTransaction.ts +++ b/packages/networks/evm-chains/src/models/CoinTransaction.ts @@ -1,20 +1,25 @@ import { Transaction } from './Transaction.ts' +import { hexToNumber } from '@multiplechain/utils' +import { Provider } from '../services/Provider.ts' import { TransactionStatusEnum } from '@multiplechain/types' -import type { AssetDirectionEnum, CoinTransactionInterface } from '@multiplechain/types' +import { AssetDirectionEnum, type CoinTransactionInterface } from '@multiplechain/types' export class CoinTransaction extends Transaction implements CoinTransactionInterface { /** * @returns Wallet address of the sender of transaction */ - getReceiver(): string { - return 'example' + async getReceiver(): Promise { + const data = await this.getData() + return data?.response.to ?? '' } /** * @returns Transfer amount of the transaction (coin) */ - getAmount(): number { - return 0 + async getAmount(): Promise { + const data = await this.getData() + const { decimals } = Provider.instance.network.nativeCurrency + return hexToNumber((data?.response.value ?? 0).toString(), decimals) } /** @@ -22,11 +27,31 @@ export class CoinTransaction extends Transaction implements CoinTransactionInter * @param address - Wallet address of the receiver or sender of the transaction, dependant on direction * @param amount Amount of assets that will be transferred */ - verifyTransfer( + async verifyTransfer( direction: AssetDirectionEnum, address: string, amount: number - ): TransactionStatusEnum { - return TransactionStatusEnum.PENDING + ): Promise { + const status = await this.getStatus() + + if (status === TransactionStatusEnum.PENDING) { + return TransactionStatusEnum.PENDING + } + + if ((await this.getAmount()) !== amount) { + return TransactionStatusEnum.FAILED + } + + if (direction === AssetDirectionEnum.INCOMING) { + if ((await this.getReceiver()).toLowerCase() !== address.toLowerCase()) { + return TransactionStatusEnum.FAILED + } + } else { + if ((await this.getSender()).toLowerCase() !== address.toLowerCase()) { + return TransactionStatusEnum.FAILED + } + } + + return TransactionStatusEnum.CONFIRMED } } diff --git a/packages/networks/evm-chains/tests/models.spec.ts b/packages/networks/evm-chains/tests/models.spec.ts index 41cbe40..1ce76cd 100644 --- a/packages/networks/evm-chains/tests/models.spec.ts +++ b/packages/networks/evm-chains/tests/models.spec.ts @@ -2,8 +2,9 @@ import { describe, it, expect } from 'vitest' import ERC20 from '../resources/erc20.json' import { Transaction } from '../src/models/Transaction.ts' -import { TransactionStatusEnum } from '@multiplechain/types' +import { AssetDirectionEnum, TransactionStatusEnum } from '@multiplechain/types' import { ContractTransaction } from '../src/models/ContractTransaction.ts' +import { CoinTransaction } from '../src/models/CoinTransaction.ts' const etherTransferTx = '0x566002399664e92f82ed654c181095bdd7ff3d3f1921d963257585891f622251' const tokenTransferTx = '0xdabda3905e585db91768f2ef877f7fbef7c0e8612c0a09c7b379981bdbc48975' @@ -64,3 +65,43 @@ describe('Contract Transaction', () => { expect(result?.args[0]).toBe('0xbBa4d06D1cEf94b35aDeCfDa893523907fdD36DE') }) }) + +describe('Coin Transaction', () => { + const tx = new CoinTransaction(etherTransferTx) + + it('Receiver', async () => { + expect((await tx.getReceiver()).toLowerCase()).toBe( + '0xb3C86232c163A988Ce4358B10A2745864Bfaa3Ba'.toLowerCase() + ) + }) + + it('Amount', async () => { + expect(await tx.getAmount()).toBe(0.002548) + }) + + it('Verify Transfer', async () => { + expect( + await tx.verifyTransfer( + AssetDirectionEnum.INCOMING, + '0xb3C86232c163A988Ce4358B10A2745864Bfaa3Ba', + 0.002548 + ) + ).toBe(TransactionStatusEnum.CONFIRMED) + + expect( + await tx.verifyTransfer( + AssetDirectionEnum.OUTGOING, + '0x74dBE9cA4F93087A27f23164d4367b8ce66C33e2', + 0.002548 + ) + ).toBe(TransactionStatusEnum.CONFIRMED) + + expect( + await tx.verifyTransfer( + AssetDirectionEnum.OUTGOING, + '0xb3C86232c163A988Ce4358B10A2745864Bfaa3Ba', + 0.002548 + ) + ).toBe(TransactionStatusEnum.FAILED) + }) +}) From 41ec1810f79022096bbd3554662eda6d5d94105b Mon Sep 17 00:00:00 2001 From: Halil Beycan <50718965+BeycanDeveloper@users.noreply.github.com> Date: Sat, 30 Mar 2024 23:36:24 +0800 Subject: [PATCH 044/114] updated --- .../networks/boilerplate/src/models/TokenTransaction.ts | 7 ------- 1 file changed, 7 deletions(-) diff --git a/packages/networks/boilerplate/src/models/TokenTransaction.ts b/packages/networks/boilerplate/src/models/TokenTransaction.ts index df303a1..f4f0bcd 100644 --- a/packages/networks/boilerplate/src/models/TokenTransaction.ts +++ b/packages/networks/boilerplate/src/models/TokenTransaction.ts @@ -17,13 +17,6 @@ export class TokenTransaction extends ContractTransaction implements TokenTransa return 0 } - /** - * @returns Token address of the transaction - */ - async getAddress(): Promise { - return 'example' - } - /** * @param direction - Direction of the transaction (token) * @param address - Wallet address of the owner or spender of the transaction, dependant on direction From 472050e0357bc3426015f413a93aec5b1bc33318 Mon Sep 17 00:00:00 2001 From: Halil Beycan <50718965+BeycanDeveloper@users.noreply.github.com> Date: Sat, 30 Mar 2024 23:37:39 +0800 Subject: [PATCH 045/114] updated --- packages/networks/boilerplate/src/models/NftTransaction.ts | 7 ------- 1 file changed, 7 deletions(-) diff --git a/packages/networks/boilerplate/src/models/NftTransaction.ts b/packages/networks/boilerplate/src/models/NftTransaction.ts index 84bbb2d..b8bfaba 100644 --- a/packages/networks/boilerplate/src/models/NftTransaction.ts +++ b/packages/networks/boilerplate/src/models/NftTransaction.ts @@ -24,13 +24,6 @@ export class NftTransaction extends ContractTransaction implements NftTransactio return 0 } - /** - * @returns Smart contract address of the transaction - */ - async getAddress(): Promise { - return 'example' - } - /** * @param direction - Direction of the transaction (nft) * @param address - Wallet address of the receiver or sender of the transaction, dependant on direction From cd07125bfa72dcb4ce8fa2c6a45e147c190fcdfc Mon Sep 17 00:00:00 2001 From: Halil Beycan <50718965+BeycanDeveloper@users.noreply.github.com> Date: Sat, 30 Mar 2024 23:51:16 +0800 Subject: [PATCH 046/114] updated --- .../boilerplate/src/models/NftTransaction.ts | 14 -------------- .../boilerplate/src/models/TokenTransaction.ts | 13 ------------- 2 files changed, 27 deletions(-) diff --git a/packages/networks/boilerplate/src/models/NftTransaction.ts b/packages/networks/boilerplate/src/models/NftTransaction.ts index b8bfaba..c81b377 100644 --- a/packages/networks/boilerplate/src/models/NftTransaction.ts +++ b/packages/networks/boilerplate/src/models/NftTransaction.ts @@ -37,18 +37,4 @@ export class NftTransaction extends ContractTransaction implements NftTransactio ): Promise { return TransactionStatusEnum.PENDING } - - /** - * @param direction - Direction of the transaction (nft) - * @param address - Wallet address of the owner or spender of the transaction, dependant on direction - * @param nftId ID of the NFT that will be approved - * @override verifyApprove() in AssetTransactionInterface - */ - async verifyApprove( - direction: AssetDirectionEnum, - address: string, - nftId: number - ): Promise { - return TransactionStatusEnum.PENDING - } } diff --git a/packages/networks/boilerplate/src/models/TokenTransaction.ts b/packages/networks/boilerplate/src/models/TokenTransaction.ts index f4f0bcd..cb75bc8 100644 --- a/packages/networks/boilerplate/src/models/TokenTransaction.ts +++ b/packages/networks/boilerplate/src/models/TokenTransaction.ts @@ -29,17 +29,4 @@ export class TokenTransaction extends ContractTransaction implements TokenTransa ): Promise { return TransactionStatusEnum.PENDING } - - /** - * @param direction - Direction of the transaction (token) - * @param address - Wallet address of the owner or spender of the transaction, dependant on direction - * @param amount Amount of tokens that will be approved - */ - async verifyApprove( - direction: AssetDirectionEnum, - address: string, - amount: number - ): Promise { - return TransactionStatusEnum.PENDING - } } From 73c1e4558609bbc90c509e8d90af42f2b5334246 Mon Sep 17 00:00:00 2001 From: Halil Beycan <50718965+BeycanDeveloper@users.noreply.github.com> Date: Sat, 30 Mar 2024 23:51:44 +0800 Subject: [PATCH 047/114] removed verifyApprove methods --- packages/types/package.json | 2 +- packages/types/src/models.ts | 24 +----------------------- 2 files changed, 2 insertions(+), 24 deletions(-) diff --git a/packages/types/package.json b/packages/types/package.json index 22ecb3d..04223d9 100644 --- a/packages/types/package.json +++ b/packages/types/package.json @@ -1,6 +1,6 @@ { "name": "@multiplechain/types", - "version": "0.1.24", + "version": "0.1.25", "type": "module", "main": "./src/index.ts", "types": "./src/index.ts", diff --git a/packages/types/src/models.ts b/packages/types/src/models.ts index a6e8992..cb6c6ae 100644 --- a/packages/types/src/models.ts +++ b/packages/types/src/models.ts @@ -92,18 +92,7 @@ export interface CoinTransactionInterface extends AssetTransactionInterface {} export interface TokenTransactionInterface extends AssetTransactionInterface, - ContractTransactionInterface { - /** - * @param direction - Direction of the transaction (token) - * @param address - Wallet address of the owner or spender of the transaction, dependant on direction - * @param amount Amount of tokens that will be approved - */ - verifyApprove: ( - direction: AssetDirectionEnum, - address: string, - amount: number - ) => Promise -} + ContractTransactionInterface {} export interface NftTransactionInterface extends Omit, @@ -124,15 +113,4 @@ export interface NftTransactionInterface address: string, nftId: number ) => Promise - - /** - * @param direction - Direction of the transaction (nft) - * @param address - Wallet address of the owner or spender of the transaction, dependant on direction - * @param nftId ID of the NFT that will be approved - */ - verifyApprove: ( - direction: AssetDirectionEnum, - address: string, - nftId: number - ) => Promise } From 73765ee306a379ba622498ff180a2dc71e26ebee Mon Sep 17 00:00:00 2001 From: Halil Beycan <50718965+BeycanDeveloper@users.noreply.github.com> Date: Sat, 30 Mar 2024 23:52:32 +0800 Subject: [PATCH 048/114] updated --- packages/networks/boilerplate/package.json | 4 ++-- packages/networks/boilerplate/pnpm-lock.yaml | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/networks/boilerplate/package.json b/packages/networks/boilerplate/package.json index f7eb6ef..2dbd3ac 100644 --- a/packages/networks/boilerplate/package.json +++ b/packages/networks/boilerplate/package.json @@ -16,7 +16,7 @@ "typecheck": "tsc --noEmit", "lint": "eslint . --ext .ts", "test": "vitest run --dir tests", - "prepublishOnly":"pnpm run build" + "prepublishOnly": "pnpm run build" }, "keywords": [ "web3", @@ -36,7 +36,7 @@ "url": "https://github.com/MultipleChain/js/issues" }, "dependencies": { - "@multiplechain/types": "^0.1.24", + "@multiplechain/types": "^0.1.25", "@multiplechain/utils": "^0.1.8" } } \ No newline at end of file diff --git a/packages/networks/boilerplate/pnpm-lock.yaml b/packages/networks/boilerplate/pnpm-lock.yaml index beee03e..e0b02af 100644 --- a/packages/networks/boilerplate/pnpm-lock.yaml +++ b/packages/networks/boilerplate/pnpm-lock.yaml @@ -6,16 +6,16 @@ settings: dependencies: '@multiplechain/types': - specifier: ^0.1.24 - version: 0.1.24 + specifier: ^0.1.25 + version: 0.1.25 '@multiplechain/utils': specifier: ^0.1.8 version: 0.1.9 packages: - /@multiplechain/types@0.1.24: - resolution: {integrity: sha512-CsfAtGf/k88h0xU6yiJUeef4vj8NwFuBV5tmMk4Y27Fbcu4TbpigutDRwgbBSY9kZbv3EbrxcniUUFfPCTc7Ow==} + /@multiplechain/types@0.1.25: + resolution: {integrity: sha512-oGBYufOUx/3mBIRPG8EaQYy9DDy5yTnId5FxMVQ6O7NusLRaFlsP02JK4fm+lXrmJV9HMhJtJpE8pWhS6MPNFw==} dev: false /@multiplechain/utils@0.1.9: From f9583809335534c64f8a4b802ebb01bc85355df9 Mon Sep 17 00:00:00 2001 From: Halil Beycan <50718965+BeycanDeveloper@users.noreply.github.com> Date: Sun, 31 Mar 2024 00:13:22 +0800 Subject: [PATCH 049/114] updated --- packages/networks/boilerplate/src/models/NftTransaction.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/packages/networks/boilerplate/src/models/NftTransaction.ts b/packages/networks/boilerplate/src/models/NftTransaction.ts index c81b377..64b85c6 100644 --- a/packages/networks/boilerplate/src/models/NftTransaction.ts +++ b/packages/networks/boilerplate/src/models/NftTransaction.ts @@ -2,7 +2,10 @@ import { ContractTransaction } from './ContractTransaction.ts' import { TransactionStatusEnum } from '@multiplechain/types' import type { NftTransactionInterface, AssetDirectionEnum } from '@multiplechain/types' -export class NftTransaction extends ContractTransaction implements NftTransactionInterface { +export class NftTransaction + extends ContractTransaction + implements Omit +{ /** * @returns Wallet address of the sender of transaction */ From a6339967416975e6d4fc65ab7392ff63dde4c597 Mon Sep 17 00:00:00 2001 From: Halil Beycan <50718965+BeycanDeveloper@users.noreply.github.com> Date: Sun, 31 Mar 2024 00:40:00 +0800 Subject: [PATCH 050/114] updated --- packages/types/package.json | 2 +- packages/types/src/models.ts | 7 ++++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/packages/types/package.json b/packages/types/package.json index 04223d9..4a8df7b 100644 --- a/packages/types/package.json +++ b/packages/types/package.json @@ -1,6 +1,6 @@ { "name": "@multiplechain/types", - "version": "0.1.25", + "version": "0.1.26", "type": "module", "main": "./src/index.ts", "types": "./src/index.ts", diff --git a/packages/types/src/models.ts b/packages/types/src/models.ts index cb6c6ae..7d8d1fe 100644 --- a/packages/types/src/models.ts +++ b/packages/types/src/models.ts @@ -76,6 +76,11 @@ export interface AssetTransactionInterface extends TransactionInterface { */ getAmount: () => Promise + /** + * @returns Wallet address of the sender of asset + */ + getFrom: () => Promise + /** * @param direction - Direction of the transaction (asset) * @param address - Wallet address of the receiver or sender of the transaction, dependant on direction @@ -95,7 +100,7 @@ export interface TokenTransactionInterface ContractTransactionInterface {} export interface NftTransactionInterface - extends Omit, + extends Omit, ContractTransactionInterface { /** * @returns ID of the NFT From 04228df37fe75a17a8829b3247ae4b7099bae1fc Mon Sep 17 00:00:00 2001 From: Halil Beycan <50718965+BeycanDeveloper@users.noreply.github.com> Date: Sun, 31 Mar 2024 00:42:03 +0800 Subject: [PATCH 051/114] updated --- packages/networks/boilerplate/package.json | 2 +- packages/networks/boilerplate/pnpm-lock.yaml | 8 ++++---- .../networks/boilerplate/src/models/NftTransaction.ts | 11 ++++------- 3 files changed, 9 insertions(+), 12 deletions(-) diff --git a/packages/networks/boilerplate/package.json b/packages/networks/boilerplate/package.json index 2dbd3ac..ed5bdef 100644 --- a/packages/networks/boilerplate/package.json +++ b/packages/networks/boilerplate/package.json @@ -36,7 +36,7 @@ "url": "https://github.com/MultipleChain/js/issues" }, "dependencies": { - "@multiplechain/types": "^0.1.25", + "@multiplechain/types": "^0.1.26", "@multiplechain/utils": "^0.1.8" } } \ No newline at end of file diff --git a/packages/networks/boilerplate/pnpm-lock.yaml b/packages/networks/boilerplate/pnpm-lock.yaml index e0b02af..1a0bb7f 100644 --- a/packages/networks/boilerplate/pnpm-lock.yaml +++ b/packages/networks/boilerplate/pnpm-lock.yaml @@ -6,16 +6,16 @@ settings: dependencies: '@multiplechain/types': - specifier: ^0.1.25 - version: 0.1.25 + specifier: ^0.1.26 + version: 0.1.26 '@multiplechain/utils': specifier: ^0.1.8 version: 0.1.9 packages: - /@multiplechain/types@0.1.25: - resolution: {integrity: sha512-oGBYufOUx/3mBIRPG8EaQYy9DDy5yTnId5FxMVQ6O7NusLRaFlsP02JK4fm+lXrmJV9HMhJtJpE8pWhS6MPNFw==} + /@multiplechain/types@0.1.26: + resolution: {integrity: sha512-vkNDfYkvf8JiSsNLliAYT0PiRoePX0scW5RG59xuhP3gWRDqArfvCm9t6VRId4p33lR90mTApceNhTOGVjfHCA==} dev: false /@multiplechain/utils@0.1.9: diff --git a/packages/networks/boilerplate/src/models/NftTransaction.ts b/packages/networks/boilerplate/src/models/NftTransaction.ts index 64b85c6..c71d6bc 100644 --- a/packages/networks/boilerplate/src/models/NftTransaction.ts +++ b/packages/networks/boilerplate/src/models/NftTransaction.ts @@ -2,10 +2,7 @@ import { ContractTransaction } from './ContractTransaction.ts' import { TransactionStatusEnum } from '@multiplechain/types' import type { NftTransactionInterface, AssetDirectionEnum } from '@multiplechain/types' -export class NftTransaction - extends ContractTransaction - implements Omit -{ +export class NftTransaction extends ContractTransaction implements NftTransactionInterface { /** * @returns Wallet address of the sender of transaction */ @@ -14,10 +11,10 @@ export class NftTransaction } /** - * @returns Transfer amount of the transaction (token) + * @returns Wallet address of the sender of asset */ - async getAmount(): Promise { - return 0 + async getFrom(): Promise { + return 'example' } /** From f00207111a74ecfaf7b044a2c670c99d5b9b1929 Mon Sep 17 00:00:00 2001 From: Halil Beycan <50718965+BeycanDeveloper@users.noreply.github.com> Date: Sun, 31 Mar 2024 00:42:39 +0800 Subject: [PATCH 052/114] all models done --- packages/networks/evm-chains/package.json | 2 +- packages/networks/evm-chains/pnpm-lock.yaml | 8 +- .../evm-chains/src/models/CoinTransaction.ts | 9 +- .../evm-chains/src/models/NftTransaction.ts | 70 ++++++++++---- .../evm-chains/src/models/TokenTransaction.ts | 87 ++++++++++++----- .../networks/evm-chains/tests/models.spec.ts | 95 +++++++++++++++++++ 6 files changed, 224 insertions(+), 47 deletions(-) diff --git a/packages/networks/evm-chains/package.json b/packages/networks/evm-chains/package.json index b581acd..e046032 100644 --- a/packages/networks/evm-chains/package.json +++ b/packages/networks/evm-chains/package.json @@ -38,7 +38,7 @@ "url": "https://github.com/MultipleChain/js/issues" }, "dependencies": { - "@multiplechain/types": "^0.1.24", + "@multiplechain/types": "^0.1.26", "@multiplechain/utils": "^0.1.9", "ethers": "^6.11.1" } diff --git a/packages/networks/evm-chains/pnpm-lock.yaml b/packages/networks/evm-chains/pnpm-lock.yaml index 67de6c2..2001bda 100644 --- a/packages/networks/evm-chains/pnpm-lock.yaml +++ b/packages/networks/evm-chains/pnpm-lock.yaml @@ -6,8 +6,8 @@ settings: dependencies: '@multiplechain/types': - specifier: ^0.1.24 - version: 0.1.24 + specifier: ^0.1.26 + version: 0.1.26 '@multiplechain/utils': specifier: ^0.1.9 version: 0.1.9 @@ -21,8 +21,8 @@ packages: resolution: {integrity: sha512-96Z2IP3mYmF1Xg2cDm8f1gWGf/HUVedQ3FMifV4kG/PQ4yEP51xDtRAEfhVNt5f/uzpNkZHwWQuUcu6D6K+Ekw==} dev: false - /@multiplechain/types@0.1.24: - resolution: {integrity: sha512-CsfAtGf/k88h0xU6yiJUeef4vj8NwFuBV5tmMk4Y27Fbcu4TbpigutDRwgbBSY9kZbv3EbrxcniUUFfPCTc7Ow==} + /@multiplechain/types@0.1.26: + resolution: {integrity: sha512-vkNDfYkvf8JiSsNLliAYT0PiRoePX0scW5RG59xuhP3gWRDqArfvCm9t6VRId4p33lR90mTApceNhTOGVjfHCA==} dev: false /@multiplechain/utils@0.1.9: diff --git a/packages/networks/evm-chains/src/models/CoinTransaction.ts b/packages/networks/evm-chains/src/models/CoinTransaction.ts index 392fc78..dacb489 100644 --- a/packages/networks/evm-chains/src/models/CoinTransaction.ts +++ b/packages/networks/evm-chains/src/models/CoinTransaction.ts @@ -13,6 +13,13 @@ export class CoinTransaction extends Transaction implements CoinTransactionInter return data?.response.to ?? '' } + /** + * @returns Wallet address of the sender of transaction + */ + async getFrom(): Promise { + return await this.getSender() + } + /** * @returns Transfer amount of the transaction (coin) */ @@ -47,7 +54,7 @@ export class CoinTransaction extends Transaction implements CoinTransactionInter return TransactionStatusEnum.FAILED } } else { - if ((await this.getSender()).toLowerCase() !== address.toLowerCase()) { + if ((await this.getFrom()).toLowerCase() !== address.toLowerCase()) { return TransactionStatusEnum.FAILED } } diff --git a/packages/networks/evm-chains/src/models/NftTransaction.ts b/packages/networks/evm-chains/src/models/NftTransaction.ts index 92dea08..f7c5bde 100644 --- a/packages/networks/evm-chains/src/models/NftTransaction.ts +++ b/packages/networks/evm-chains/src/models/NftTransaction.ts @@ -1,34 +1,46 @@ +import ERC721 from '../../resources/erc721.json' import { ContractTransaction } from './ContractTransaction.ts' -import { TransactionStatusEnum } from '@multiplechain/types' -import type { NftTransactionInterface, AssetDirectionEnum } from '@multiplechain/types' +import type { NftTransactionInterface } from '@multiplechain/types' +import { TransactionStatusEnum, AssetDirectionEnum } from '@multiplechain/types' export class NftTransaction extends ContractTransaction implements NftTransactionInterface { /** * @returns Wallet address of the sender of transaction */ - getReceiver(): string { - return 'example' - } + async getReceiver(): Promise { + const decoded = await this.decodeData(ERC721) + if (decoded === null) { + return '' + } - /** - * @returns Transfer amount of the transaction (token) - */ - getAmount(): number { - return 0 + if (decoded.name === 'transferFrom') { + return decoded.args[1] + } + + return decoded.args[0] } /** - * @returns ID of the NFT + * @returns Wallet address of the sender of transaction */ - getNftId(): number { - return 0 + async getFrom(): Promise { + const decoded = await this.decodeData(ERC721) + if (decoded === null) { + return '' + } + + if (decoded.name === 'transferFrom') { + return decoded.args[0] + } + + return await this.getSender() } /** - * @returns Smart contract address of the transaction + * @returns ID of the NFT */ - getAddress(): string { - return 'example' + async getNftId(): Promise { + return Number((await this.decodeData(ERC721))?.args[2] ?? 0) } /** @@ -37,11 +49,31 @@ export class NftTransaction extends ContractTransaction implements NftTransactio * @param nftId ID of the NFT that will be transferred * @override verifyTransfer() in AssetTransactionInterface */ - verifyTransfer( + async verifyTransfer( direction: AssetDirectionEnum, address: string, nftId: number - ): TransactionStatusEnum { - return TransactionStatusEnum.PENDING + ): Promise { + const status = await this.getStatus() + + if (status === TransactionStatusEnum.PENDING) { + return TransactionStatusEnum.PENDING + } + + if ((await this.getNftId()) !== nftId) { + return TransactionStatusEnum.FAILED + } + + if (direction === AssetDirectionEnum.INCOMING) { + if ((await this.getReceiver()).toLowerCase() !== address.toLowerCase()) { + return TransactionStatusEnum.FAILED + } + } else { + if ((await this.getFrom()).toLowerCase() !== address.toLowerCase()) { + return TransactionStatusEnum.FAILED + } + } + + return TransactionStatusEnum.CONFIRMED } } diff --git a/packages/networks/evm-chains/src/models/TokenTransaction.ts b/packages/networks/evm-chains/src/models/TokenTransaction.ts index c87cd2b..9fbe497 100644 --- a/packages/networks/evm-chains/src/models/TokenTransaction.ts +++ b/packages/networks/evm-chains/src/models/TokenTransaction.ts @@ -1,40 +1,63 @@ +import { Token } from '../assets/Token.ts' +import ERC20 from '../../resources/erc20.json' +import { hexToNumber } from '@multiplechain/utils' import { ContractTransaction } from './ContractTransaction.ts' import { TransactionStatusEnum } from '@multiplechain/types' -import type { AssetDirectionEnum, TokenTransactionInterface } from '@multiplechain/types' +import { AssetDirectionEnum, type TokenTransactionInterface } from '@multiplechain/types' export class TokenTransaction extends ContractTransaction implements TokenTransactionInterface { /** * @returns Wallet address of the sender of transaction */ - getReceiver(): string { - return 'example' + async getReceiver(): Promise { + const decoded = await this.decodeData(ERC20) + console.log(decoded) + if (decoded === null) { + return '' + } + + if (decoded.name === 'transferFrom') { + return decoded.args[1] + } + + return decoded.args[0] } /** - * @returns Transfer amount of the transaction (token) + * @returns Wallet address of the sender of transaction */ - getAmount(): number { - return 0 + async getFrom(): Promise { + const decoded = await this.decodeData(ERC20) + if (decoded === null) { + return '' + } + + if (decoded.name === 'transferFrom') { + return decoded.args[0] + } + + return await this.getSender() } /** - * @returns Token address of the transaction + * @returns Wallet address of the sender of transaction */ - getAddress(): string { - return 'example' - } /** - * @param direction - Direction of the transaction (token) - * @param address - Wallet address of the owner or spender of the transaction, dependant on direction - * @param amount Amount of tokens that will be approved + * @returns Transfer amount of the transaction (token) */ - verifyTransfer( - direction: AssetDirectionEnum, - address: string, - amount: number - ): TransactionStatusEnum { - return TransactionStatusEnum.PENDING + async getAmount(): Promise { + const token = new Token(await this.getAddress()) + const decoded = await this.decodeData(ERC20) + if (decoded === null) { + return 0 + } + + if (decoded.name === 'transferFrom') { + return hexToNumber((decoded.args[2] as bigint).toString(), await token.getDecimals()) + } + + return hexToNumber((decoded.args[1] as bigint).toString(), await token.getDecimals()) } /** @@ -42,11 +65,31 @@ export class TokenTransaction extends ContractTransaction implements TokenTransa * @param address - Wallet address of the owner or spender of the transaction, dependant on direction * @param amount Amount of tokens that will be approved */ - verifyApprove( + async verifyTransfer( direction: AssetDirectionEnum, address: string, amount: number - ): TransactionStatusEnum { - return TransactionStatusEnum.PENDING + ): Promise { + const status = await this.getStatus() + + if (status === TransactionStatusEnum.PENDING) { + return TransactionStatusEnum.PENDING + } + + if ((await this.getAmount()) !== amount) { + return TransactionStatusEnum.FAILED + } + + if (direction === AssetDirectionEnum.INCOMING) { + if ((await this.getReceiver()).toLowerCase() !== address.toLowerCase()) { + return TransactionStatusEnum.FAILED + } + } else { + if ((await this.getFrom()).toLowerCase() !== address.toLowerCase()) { + return TransactionStatusEnum.FAILED + } + } + + return TransactionStatusEnum.CONFIRMED } } diff --git a/packages/networks/evm-chains/tests/models.spec.ts b/packages/networks/evm-chains/tests/models.spec.ts index 1ce76cd..2517ad6 100644 --- a/packages/networks/evm-chains/tests/models.spec.ts +++ b/packages/networks/evm-chains/tests/models.spec.ts @@ -5,9 +5,12 @@ import { Transaction } from '../src/models/Transaction.ts' import { AssetDirectionEnum, TransactionStatusEnum } from '@multiplechain/types' import { ContractTransaction } from '../src/models/ContractTransaction.ts' import { CoinTransaction } from '../src/models/CoinTransaction.ts' +import { TokenTransaction } from '../src/models/TokenTransaction.ts' +import { NftTransaction } from '../src/models/NftTransaction.ts' const etherTransferTx = '0x566002399664e92f82ed654c181095bdd7ff3d3f1921d963257585891f622251' const tokenTransferTx = '0xdabda3905e585db91768f2ef877f7fbef7c0e8612c0a09c7b379981bdbc48975' +const nftTransferTx = '0x272a4698cd2062f2463481cf9eb78b68b35d59938383679b7642e6d669ac87eb' describe('Transaction', () => { const tx = new Transaction(etherTransferTx) @@ -105,3 +108,95 @@ describe('Coin Transaction', () => { ).toBe(TransactionStatusEnum.FAILED) }) }) + +describe('Token Transaction', () => { + const tx = new TokenTransaction(tokenTransferTx) + + it('Receiver', async () => { + expect((await tx.getReceiver()).toLowerCase()).toBe( + '0xbBa4d06D1cEf94b35aDeCfDa893523907fdD36DE'.toLowerCase() + ) + }) + + it('Amount', async () => { + expect(await tx.getAmount()).toBe(1) + }) + + it('Verify Transfer', async () => { + expect( + await tx.verifyTransfer( + AssetDirectionEnum.INCOMING, + '0xbBa4d06D1cEf94b35aDeCfDa893523907fdD36DE', + 1 + ) + ).toBe(TransactionStatusEnum.CONFIRMED) + + expect( + await tx.verifyTransfer( + AssetDirectionEnum.OUTGOING, + '0x110600bF0399174520a159ed425f0D272Ff8b459', + 1 + ) + ).toBe(TransactionStatusEnum.CONFIRMED) + + expect( + await tx.verifyTransfer( + AssetDirectionEnum.OUTGOING, + '0xbBa4d06D1cEf94b35aDeCfDa893523907fdD36DE', + 1 + ) + ).toBe(TransactionStatusEnum.FAILED) + }) +}) + +describe('NFT Transaction', () => { + const tx = new NftTransaction(nftTransferTx) + + it('Receiver', async () => { + expect((await tx.getReceiver()).toLowerCase()).toBe( + '0x110600bF0399174520a159ed425f0D272Ff8b459'.toLowerCase() + ) + }) + + it('From', async () => { + expect((await tx.getFrom()).toLowerCase()).toBe( + '0xbBa4d06D1cEf94b35aDeCfDa893523907fdD36DE'.toLowerCase() + ) + }) + + it('Sender', async () => { + expect((await tx.getSender()).toLowerCase()).toBe( + '0x110600bF0399174520a159ed425f0D272Ff8b459'.toLowerCase() + ) + }) + + it('NFT ID', async () => { + expect(await tx.getNftId()).toBe(7) + }) + + it('Verify Transfer', async () => { + expect( + await tx.verifyTransfer( + AssetDirectionEnum.INCOMING, + '0x110600bF0399174520a159ed425f0D272Ff8b459', + 7 + ) + ).toBe(TransactionStatusEnum.CONFIRMED) + + expect( + await tx.verifyTransfer( + AssetDirectionEnum.OUTGOING, + '0xbBa4d06D1cEf94b35aDeCfDa893523907fdD36DE', + 7 + ) + ).toBe(TransactionStatusEnum.CONFIRMED) + + expect( + await tx.verifyTransfer( + AssetDirectionEnum.OUTGOING, + '0x110600bF0399174520a159ed425f0D272Ff8b459', + 7 + ) + ).toBe(TransactionStatusEnum.FAILED) + }) +}) From b57587cc588f1abb821f567fd0f4f1ae344c2f1e Mon Sep 17 00:00:00 2001 From: Halil Beycan <50718965+BeycanDeveloper@users.noreply.github.com> Date: Sun, 31 Mar 2024 00:43:35 +0800 Subject: [PATCH 053/114] updated --- packages/networks/evm-chains/src/models/NftTransaction.ts | 2 ++ packages/networks/evm-chains/src/models/TokenTransaction.ts | 3 ++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/packages/networks/evm-chains/src/models/NftTransaction.ts b/packages/networks/evm-chains/src/models/NftTransaction.ts index f7c5bde..96945d4 100644 --- a/packages/networks/evm-chains/src/models/NftTransaction.ts +++ b/packages/networks/evm-chains/src/models/NftTransaction.ts @@ -9,6 +9,7 @@ export class NftTransaction extends ContractTransaction implements NftTransactio */ async getReceiver(): Promise { const decoded = await this.decodeData(ERC721) + if (decoded === null) { return '' } @@ -25,6 +26,7 @@ export class NftTransaction extends ContractTransaction implements NftTransactio */ async getFrom(): Promise { const decoded = await this.decodeData(ERC721) + if (decoded === null) { return '' } diff --git a/packages/networks/evm-chains/src/models/TokenTransaction.ts b/packages/networks/evm-chains/src/models/TokenTransaction.ts index 9fbe497..4bc064c 100644 --- a/packages/networks/evm-chains/src/models/TokenTransaction.ts +++ b/packages/networks/evm-chains/src/models/TokenTransaction.ts @@ -11,7 +11,7 @@ export class TokenTransaction extends ContractTransaction implements TokenTransa */ async getReceiver(): Promise { const decoded = await this.decodeData(ERC20) - console.log(decoded) + if (decoded === null) { return '' } @@ -28,6 +28,7 @@ export class TokenTransaction extends ContractTransaction implements TokenTransa */ async getFrom(): Promise { const decoded = await this.decodeData(ERC20) + if (decoded === null) { return '' } From 386790523ad81c40680c5f04e534e39e2644a791 Mon Sep 17 00:00:00 2001 From: Halil Beycan <50718965+BeycanDeveloper@users.noreply.github.com> Date: Sun, 31 Mar 2024 01:08:32 +0800 Subject: [PATCH 054/114] updated --- .../networks/boilerplate/tests/assets.spec.ts | 7 + .../networks/boilerplate/tests/models.spec.ts | 7 + .../boilerplate/tests/services.spec.ts | 7 + .../networks/evm-chains/tests/models.spec.ts | 123 +++++++----------- 4 files changed, 66 insertions(+), 78 deletions(-) diff --git a/packages/networks/boilerplate/tests/assets.spec.ts b/packages/networks/boilerplate/tests/assets.spec.ts index e69de29..34c5579 100644 --- a/packages/networks/boilerplate/tests/assets.spec.ts +++ b/packages/networks/boilerplate/tests/assets.spec.ts @@ -0,0 +1,7 @@ +import { describe, it, expect } from 'vitest' + +describe('example', () => { + it('should work', () => { + expect(1 + 1).toBe(2) + }) +}) diff --git a/packages/networks/boilerplate/tests/models.spec.ts b/packages/networks/boilerplate/tests/models.spec.ts index e69de29..34c5579 100644 --- a/packages/networks/boilerplate/tests/models.spec.ts +++ b/packages/networks/boilerplate/tests/models.spec.ts @@ -0,0 +1,7 @@ +import { describe, it, expect } from 'vitest' + +describe('example', () => { + it('should work', () => { + expect(1 + 1).toBe(2) + }) +}) diff --git a/packages/networks/boilerplate/tests/services.spec.ts b/packages/networks/boilerplate/tests/services.spec.ts index e69de29..34c5579 100644 --- a/packages/networks/boilerplate/tests/services.spec.ts +++ b/packages/networks/boilerplate/tests/services.spec.ts @@ -0,0 +1,7 @@ +import { describe, it, expect } from 'vitest' + +describe('example', () => { + it('should work', () => { + expect(1 + 1).toBe(2) + }) +}) diff --git a/packages/networks/evm-chains/tests/models.spec.ts b/packages/networks/evm-chains/tests/models.spec.ts index 2517ad6..8294fa9 100644 --- a/packages/networks/evm-chains/tests/models.spec.ts +++ b/packages/networks/evm-chains/tests/models.spec.ts @@ -12,6 +12,19 @@ const etherTransferTx = '0x566002399664e92f82ed654c181095bdd7ff3d3f1921d96325758 const tokenTransferTx = '0xdabda3905e585db91768f2ef877f7fbef7c0e8612c0a09c7b379981bdbc48975' const nftTransferTx = '0x272a4698cd2062f2463481cf9eb78b68b35d59938383679b7642e6d669ac87eb' +const nftId = 7 +const tokenAmount = 1 +const coinAmount = 0.002548 + +const coinSender = '0x74dBE9cA4F93087A27f23164d4367b8ce66C33e2' +const coinReceiver = '0xb3C86232c163A988Ce4358B10A2745864Bfaa3Ba' + +const tokenSender = '0x110600bF0399174520a159ed425f0D272Ff8b459' +const tokenReceiver = '0xbBa4d06D1cEf94b35aDeCfDa893523907fdD36DE' + +const nftSender = '0xbBa4d06D1cEf94b35aDeCfDa893523907fdD36DE' +const nftReceiver = '0x110600bF0399174520a159ed425f0D272Ff8b459' + describe('Transaction', () => { const tx = new Transaction(etherTransferTx) it('Id', async () => { @@ -29,7 +42,7 @@ describe('Transaction', () => { }) it('Sender', async () => { - expect(await tx.getSender()).toBe('0x74dBE9cA4F93087A27f23164d4367b8ce66C33e2') + expect(await tx.getSender()).toBe(coinSender) }) it('Fee', async () => { @@ -73,39 +86,25 @@ describe('Coin Transaction', () => { const tx = new CoinTransaction(etherTransferTx) it('Receiver', async () => { - expect((await tx.getReceiver()).toLowerCase()).toBe( - '0xb3C86232c163A988Ce4358B10A2745864Bfaa3Ba'.toLowerCase() - ) + expect((await tx.getReceiver()).toLowerCase()).toBe(coinReceiver.toLowerCase()) }) it('Amount', async () => { - expect(await tx.getAmount()).toBe(0.002548) + expect(await tx.getAmount()).toBe(coinAmount) }) it('Verify Transfer', async () => { - expect( - await tx.verifyTransfer( - AssetDirectionEnum.INCOMING, - '0xb3C86232c163A988Ce4358B10A2745864Bfaa3Ba', - 0.002548 - ) - ).toBe(TransactionStatusEnum.CONFIRMED) + expect(await tx.verifyTransfer(AssetDirectionEnum.INCOMING, coinReceiver, coinAmount)).toBe( + TransactionStatusEnum.CONFIRMED + ) - expect( - await tx.verifyTransfer( - AssetDirectionEnum.OUTGOING, - '0x74dBE9cA4F93087A27f23164d4367b8ce66C33e2', - 0.002548 - ) - ).toBe(TransactionStatusEnum.CONFIRMED) + expect(await tx.verifyTransfer(AssetDirectionEnum.OUTGOING, coinSender, coinAmount)).toBe( + TransactionStatusEnum.CONFIRMED + ) - expect( - await tx.verifyTransfer( - AssetDirectionEnum.OUTGOING, - '0xb3C86232c163A988Ce4358B10A2745864Bfaa3Ba', - 0.002548 - ) - ).toBe(TransactionStatusEnum.FAILED) + expect(await tx.verifyTransfer(AssetDirectionEnum.OUTGOING, coinReceiver, coinAmount)).toBe( + TransactionStatusEnum.FAILED + ) }) }) @@ -113,38 +112,24 @@ describe('Token Transaction', () => { const tx = new TokenTransaction(tokenTransferTx) it('Receiver', async () => { - expect((await tx.getReceiver()).toLowerCase()).toBe( - '0xbBa4d06D1cEf94b35aDeCfDa893523907fdD36DE'.toLowerCase() - ) + expect((await tx.getReceiver()).toLowerCase()).toBe(tokenReceiver.toLowerCase()) }) it('Amount', async () => { - expect(await tx.getAmount()).toBe(1) + expect(await tx.getAmount()).toBe(tokenAmount) }) it('Verify Transfer', async () => { expect( - await tx.verifyTransfer( - AssetDirectionEnum.INCOMING, - '0xbBa4d06D1cEf94b35aDeCfDa893523907fdD36DE', - 1 - ) + await tx.verifyTransfer(AssetDirectionEnum.INCOMING, tokenReceiver, tokenAmount) ).toBe(TransactionStatusEnum.CONFIRMED) - expect( - await tx.verifyTransfer( - AssetDirectionEnum.OUTGOING, - '0x110600bF0399174520a159ed425f0D272Ff8b459', - 1 - ) - ).toBe(TransactionStatusEnum.CONFIRMED) + expect(await tx.verifyTransfer(AssetDirectionEnum.OUTGOING, tokenSender, tokenAmount)).toBe( + TransactionStatusEnum.CONFIRMED + ) expect( - await tx.verifyTransfer( - AssetDirectionEnum.OUTGOING, - '0xbBa4d06D1cEf94b35aDeCfDa893523907fdD36DE', - 1 - ) + await tx.verifyTransfer(AssetDirectionEnum.OUTGOING, tokenReceiver, tokenAmount) ).toBe(TransactionStatusEnum.FAILED) }) }) @@ -153,50 +138,32 @@ describe('NFT Transaction', () => { const tx = new NftTransaction(nftTransferTx) it('Receiver', async () => { - expect((await tx.getReceiver()).toLowerCase()).toBe( - '0x110600bF0399174520a159ed425f0D272Ff8b459'.toLowerCase() - ) + expect((await tx.getReceiver()).toLowerCase()).toBe(nftReceiver.toLowerCase()) }) it('From', async () => { - expect((await tx.getFrom()).toLowerCase()).toBe( - '0xbBa4d06D1cEf94b35aDeCfDa893523907fdD36DE'.toLowerCase() - ) + expect((await tx.getFrom()).toLowerCase()).toBe(nftSender.toLowerCase()) }) it('Sender', async () => { - expect((await tx.getSender()).toLowerCase()).toBe( - '0x110600bF0399174520a159ed425f0D272Ff8b459'.toLowerCase() - ) + expect((await tx.getSender()).toLowerCase()).toBe(nftReceiver.toLowerCase()) }) it('NFT ID', async () => { - expect(await tx.getNftId()).toBe(7) + expect(await tx.getNftId()).toBe(nftId) }) it('Verify Transfer', async () => { - expect( - await tx.verifyTransfer( - AssetDirectionEnum.INCOMING, - '0x110600bF0399174520a159ed425f0D272Ff8b459', - 7 - ) - ).toBe(TransactionStatusEnum.CONFIRMED) + expect(await tx.verifyTransfer(AssetDirectionEnum.INCOMING, nftReceiver, nftId)).toBe( + TransactionStatusEnum.CONFIRMED + ) - expect( - await tx.verifyTransfer( - AssetDirectionEnum.OUTGOING, - '0xbBa4d06D1cEf94b35aDeCfDa893523907fdD36DE', - 7 - ) - ).toBe(TransactionStatusEnum.CONFIRMED) + expect(await tx.verifyTransfer(AssetDirectionEnum.OUTGOING, nftSender, nftId)).toBe( + TransactionStatusEnum.CONFIRMED + ) - expect( - await tx.verifyTransfer( - AssetDirectionEnum.OUTGOING, - '0x110600bF0399174520a159ed425f0D272Ff8b459', - 7 - ) - ).toBe(TransactionStatusEnum.FAILED) + expect(await tx.verifyTransfer(AssetDirectionEnum.OUTGOING, nftReceiver, nftId)).toBe( + TransactionStatusEnum.FAILED + ) }) }) From 50e3b228bbdcf700e7d57c234424ab42d5179b95 Mon Sep 17 00:00:00 2001 From: Halil Beycan <50718965+BeycanDeveloper@users.noreply.github.com> Date: Sun, 31 Mar 2024 09:37:42 +0800 Subject: [PATCH 055/114] updated --- packages/types/package.json | 2 +- packages/types/src/models.ts | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/packages/types/package.json b/packages/types/package.json index 4a8df7b..b7288bd 100644 --- a/packages/types/package.json +++ b/packages/types/package.json @@ -1,6 +1,6 @@ { "name": "@multiplechain/types", - "version": "0.1.26", + "version": "0.1.27", "type": "module", "main": "./src/index.ts", "types": "./src/index.ts", diff --git a/packages/types/src/models.ts b/packages/types/src/models.ts index 7d8d1fe..ac0c068 100644 --- a/packages/types/src/models.ts +++ b/packages/types/src/models.ts @@ -28,9 +28,9 @@ export interface TransactionInterface { getUrl: () => string /** - * @returns Wallet address of the sender of transaction + * @returns Wallet address of the signer of transaction */ - getSender: () => Promise + getSigner: () => Promise /** * @returns Transaction fee as native coin amount @@ -72,14 +72,14 @@ export interface AssetTransactionInterface extends TransactionInterface { getReceiver: () => Promise /** - * @returns Transfer amount of the transaction (coin) + * @returns Wallet address of the sender of asset */ - getAmount: () => Promise + getSender: () => Promise /** - * @returns Wallet address of the sender of asset + * @returns Transfer amount of the transaction (coin) */ - getFrom: () => Promise + getAmount: () => Promise /** * @param direction - Direction of the transaction (asset) From 013a8c4203bdc3a1c196c7a5afcbd71c39835223 Mon Sep 17 00:00:00 2001 From: Halil Beycan <50718965+BeycanDeveloper@users.noreply.github.com> Date: Sun, 31 Mar 2024 09:38:56 +0800 Subject: [PATCH 056/114] updated --- packages/networks/boilerplate/package.json | 2 +- packages/networks/boilerplate/pnpm-lock.yaml | 8 ++++---- .../networks/boilerplate/src/models/CoinTransaction.ts | 7 +++++++ .../networks/boilerplate/src/models/NftTransaction.ts | 4 ++-- .../networks/boilerplate/src/models/TokenTransaction.ts | 7 +++++++ packages/networks/boilerplate/src/models/Transaction.ts | 2 +- 6 files changed, 22 insertions(+), 8 deletions(-) diff --git a/packages/networks/boilerplate/package.json b/packages/networks/boilerplate/package.json index ed5bdef..c833c5b 100644 --- a/packages/networks/boilerplate/package.json +++ b/packages/networks/boilerplate/package.json @@ -36,7 +36,7 @@ "url": "https://github.com/MultipleChain/js/issues" }, "dependencies": { - "@multiplechain/types": "^0.1.26", + "@multiplechain/types": "^0.1.27", "@multiplechain/utils": "^0.1.8" } } \ No newline at end of file diff --git a/packages/networks/boilerplate/pnpm-lock.yaml b/packages/networks/boilerplate/pnpm-lock.yaml index 1a0bb7f..75818cf 100644 --- a/packages/networks/boilerplate/pnpm-lock.yaml +++ b/packages/networks/boilerplate/pnpm-lock.yaml @@ -6,16 +6,16 @@ settings: dependencies: '@multiplechain/types': - specifier: ^0.1.26 - version: 0.1.26 + specifier: ^0.1.27 + version: 0.1.27 '@multiplechain/utils': specifier: ^0.1.8 version: 0.1.9 packages: - /@multiplechain/types@0.1.26: - resolution: {integrity: sha512-vkNDfYkvf8JiSsNLliAYT0PiRoePX0scW5RG59xuhP3gWRDqArfvCm9t6VRId4p33lR90mTApceNhTOGVjfHCA==} + /@multiplechain/types@0.1.27: + resolution: {integrity: sha512-lVQHp8j6rBMPwnkFLK0UsG6hL+v1ECSQc+XVkI/hdvvFfM6H4vqVTwzgHtq4UASONrEbqqbg4S52XDfV/ek7MA==} dev: false /@multiplechain/utils@0.1.9: diff --git a/packages/networks/boilerplate/src/models/CoinTransaction.ts b/packages/networks/boilerplate/src/models/CoinTransaction.ts index ec93b84..8a02b9a 100644 --- a/packages/networks/boilerplate/src/models/CoinTransaction.ts +++ b/packages/networks/boilerplate/src/models/CoinTransaction.ts @@ -10,6 +10,13 @@ export class CoinTransaction extends Transaction implements CoinTransactionInter return 'example' } + /** + * @returns Wallet address of the sender of transaction + */ + async getSender(): Promise { + return 'example' + } + /** * @returns Transfer amount of the transaction (coin) */ diff --git a/packages/networks/boilerplate/src/models/NftTransaction.ts b/packages/networks/boilerplate/src/models/NftTransaction.ts index c71d6bc..14500b7 100644 --- a/packages/networks/boilerplate/src/models/NftTransaction.ts +++ b/packages/networks/boilerplate/src/models/NftTransaction.ts @@ -11,9 +11,9 @@ export class NftTransaction extends ContractTransaction implements NftTransactio } /** - * @returns Wallet address of the sender of asset + * @returns Wallet address of the sender of transaction */ - async getFrom(): Promise { + async getSender(): Promise { return 'example' } diff --git a/packages/networks/boilerplate/src/models/TokenTransaction.ts b/packages/networks/boilerplate/src/models/TokenTransaction.ts index cb75bc8..62f3bf0 100644 --- a/packages/networks/boilerplate/src/models/TokenTransaction.ts +++ b/packages/networks/boilerplate/src/models/TokenTransaction.ts @@ -10,6 +10,13 @@ export class TokenTransaction extends ContractTransaction implements TokenTransa return 'example' } + /** + * @returns Wallet address of the sender of transaction + */ + async getSender(): Promise { + return 'example' + } + /** * @returns Transfer amount of the transaction (token) */ diff --git a/packages/networks/boilerplate/src/models/Transaction.ts b/packages/networks/boilerplate/src/models/Transaction.ts index 9ae82b4..6c68dde 100644 --- a/packages/networks/boilerplate/src/models/Transaction.ts +++ b/packages/networks/boilerplate/src/models/Transaction.ts @@ -40,7 +40,7 @@ export class Transaction implements TransactionInterface { /** * @returns Wallet address of the sender of transaction */ - async getSender(): Promise { + async getSigner(): Promise { return 'example' } From 89ccb7877fed1fd92a87a3659229e3855b73a803 Mon Sep 17 00:00:00 2001 From: Halil Beycan <50718965+BeycanDeveloper@users.noreply.github.com> Date: Sun, 31 Mar 2024 09:52:12 +0800 Subject: [PATCH 057/114] updated for new types --- packages/networks/evm-chains/package.json | 2 +- packages/networks/evm-chains/pnpm-lock.yaml | 8 ++++---- .../networks/evm-chains/src/models/CoinTransaction.ts | 6 +++--- packages/networks/evm-chains/src/models/NftTransaction.ts | 6 +++--- .../networks/evm-chains/src/models/TokenTransaction.ts | 6 +++--- packages/networks/evm-chains/src/models/Transaction.ts | 2 +- 6 files changed, 15 insertions(+), 15 deletions(-) diff --git a/packages/networks/evm-chains/package.json b/packages/networks/evm-chains/package.json index e046032..bdf0f62 100644 --- a/packages/networks/evm-chains/package.json +++ b/packages/networks/evm-chains/package.json @@ -38,7 +38,7 @@ "url": "https://github.com/MultipleChain/js/issues" }, "dependencies": { - "@multiplechain/types": "^0.1.26", + "@multiplechain/types": "^0.1.27", "@multiplechain/utils": "^0.1.9", "ethers": "^6.11.1" } diff --git a/packages/networks/evm-chains/pnpm-lock.yaml b/packages/networks/evm-chains/pnpm-lock.yaml index 2001bda..5021489 100644 --- a/packages/networks/evm-chains/pnpm-lock.yaml +++ b/packages/networks/evm-chains/pnpm-lock.yaml @@ -6,8 +6,8 @@ settings: dependencies: '@multiplechain/types': - specifier: ^0.1.26 - version: 0.1.26 + specifier: ^0.1.27 + version: 0.1.27 '@multiplechain/utils': specifier: ^0.1.9 version: 0.1.9 @@ -21,8 +21,8 @@ packages: resolution: {integrity: sha512-96Z2IP3mYmF1Xg2cDm8f1gWGf/HUVedQ3FMifV4kG/PQ4yEP51xDtRAEfhVNt5f/uzpNkZHwWQuUcu6D6K+Ekw==} dev: false - /@multiplechain/types@0.1.26: - resolution: {integrity: sha512-vkNDfYkvf8JiSsNLliAYT0PiRoePX0scW5RG59xuhP3gWRDqArfvCm9t6VRId4p33lR90mTApceNhTOGVjfHCA==} + /@multiplechain/types@0.1.27: + resolution: {integrity: sha512-lVQHp8j6rBMPwnkFLK0UsG6hL+v1ECSQc+XVkI/hdvvFfM6H4vqVTwzgHtq4UASONrEbqqbg4S52XDfV/ek7MA==} dev: false /@multiplechain/utils@0.1.9: diff --git a/packages/networks/evm-chains/src/models/CoinTransaction.ts b/packages/networks/evm-chains/src/models/CoinTransaction.ts index dacb489..6c0202a 100644 --- a/packages/networks/evm-chains/src/models/CoinTransaction.ts +++ b/packages/networks/evm-chains/src/models/CoinTransaction.ts @@ -16,8 +16,8 @@ export class CoinTransaction extends Transaction implements CoinTransactionInter /** * @returns Wallet address of the sender of transaction */ - async getFrom(): Promise { - return await this.getSender() + async getSender(): Promise { + return await this.getSigner() } /** @@ -54,7 +54,7 @@ export class CoinTransaction extends Transaction implements CoinTransactionInter return TransactionStatusEnum.FAILED } } else { - if ((await this.getFrom()).toLowerCase() !== address.toLowerCase()) { + if ((await this.getSender()).toLowerCase() !== address.toLowerCase()) { return TransactionStatusEnum.FAILED } } diff --git a/packages/networks/evm-chains/src/models/NftTransaction.ts b/packages/networks/evm-chains/src/models/NftTransaction.ts index 96945d4..5b87a09 100644 --- a/packages/networks/evm-chains/src/models/NftTransaction.ts +++ b/packages/networks/evm-chains/src/models/NftTransaction.ts @@ -24,7 +24,7 @@ export class NftTransaction extends ContractTransaction implements NftTransactio /** * @returns Wallet address of the sender of transaction */ - async getFrom(): Promise { + async getSender(): Promise { const decoded = await this.decodeData(ERC721) if (decoded === null) { @@ -35,7 +35,7 @@ export class NftTransaction extends ContractTransaction implements NftTransactio return decoded.args[0] } - return await this.getSender() + return await this.getSigner() } /** @@ -71,7 +71,7 @@ export class NftTransaction extends ContractTransaction implements NftTransactio return TransactionStatusEnum.FAILED } } else { - if ((await this.getFrom()).toLowerCase() !== address.toLowerCase()) { + if ((await this.getSender()).toLowerCase() !== address.toLowerCase()) { return TransactionStatusEnum.FAILED } } diff --git a/packages/networks/evm-chains/src/models/TokenTransaction.ts b/packages/networks/evm-chains/src/models/TokenTransaction.ts index 4bc064c..d3a89f7 100644 --- a/packages/networks/evm-chains/src/models/TokenTransaction.ts +++ b/packages/networks/evm-chains/src/models/TokenTransaction.ts @@ -26,7 +26,7 @@ export class TokenTransaction extends ContractTransaction implements TokenTransa /** * @returns Wallet address of the sender of transaction */ - async getFrom(): Promise { + async getSender(): Promise { const decoded = await this.decodeData(ERC20) if (decoded === null) { @@ -37,7 +37,7 @@ export class TokenTransaction extends ContractTransaction implements TokenTransa return decoded.args[0] } - return await this.getSender() + return await this.getSigner() } /** @@ -86,7 +86,7 @@ export class TokenTransaction extends ContractTransaction implements TokenTransa return TransactionStatusEnum.FAILED } } else { - if ((await this.getFrom()).toLowerCase() !== address.toLowerCase()) { + if ((await this.getSender()).toLowerCase() !== address.toLowerCase()) { return TransactionStatusEnum.FAILED } } diff --git a/packages/networks/evm-chains/src/models/Transaction.ts b/packages/networks/evm-chains/src/models/Transaction.ts index 63f3e70..5b31158 100644 --- a/packages/networks/evm-chains/src/models/Transaction.ts +++ b/packages/networks/evm-chains/src/models/Transaction.ts @@ -107,7 +107,7 @@ export class Transaction implements TransactionInterface { /** * @returns Wallet address of the sender of transaction */ - async getSender(): Promise { + async getSigner(): Promise { const data = await this.getData() return data?.response.from ?? '' } From ca8241271bb4bc94364111b10acaa523b476cc6c Mon Sep 17 00:00:00 2001 From: Halil Beycan <50718965+BeycanDeveloper@users.noreply.github.com> Date: Sun, 31 Mar 2024 11:09:22 +0800 Subject: [PATCH 058/114] updated --- packages/types/package.json | 2 +- .../services/TransactionListenerInterface.ts | 20 ++++++++++++++++++- 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/packages/types/package.json b/packages/types/package.json index b7288bd..6412dc2 100644 --- a/packages/types/package.json +++ b/packages/types/package.json @@ -1,6 +1,6 @@ { "name": "@multiplechain/types", - "version": "0.1.27", + "version": "0.1.28", "type": "module", "main": "./src/index.ts", "types": "./src/index.ts", diff --git a/packages/types/src/services/TransactionListenerInterface.ts b/packages/types/src/services/TransactionListenerInterface.ts index 9452446..656339d 100644 --- a/packages/types/src/services/TransactionListenerInterface.ts +++ b/packages/types/src/services/TransactionListenerInterface.ts @@ -13,7 +13,7 @@ import type { AssetDirectionEnum } from '../enums.ts' * Filter types for each transaction type in TransactionListenerInterface */ interface TransactionListenerFilterInterface { - sender?: string + signer?: string } interface ContractTransactionListenerFilterInterface extends TransactionListenerFilterInterface { @@ -21,6 +21,7 @@ interface ContractTransactionListenerFilterInterface extends TransactionListener } interface AssetTransactionListenerFilterInterface extends TransactionListenerFilterInterface { + sender?: string receiver?: string direction?: AssetDirectionEnum } @@ -111,6 +112,13 @@ export interface TransactionListenerInterface { */ callbacks: TransactionListenerCallbackType[] + /** + * 'status' is a boolean that shows the status of the listener. + * If 'status' is true, the listener is active. + * If 'status' is false, the listener is inactive. + */ + status: boolean + /** * 'filter' is an object that has values depending on transaction listener type. * E.g. no matter which type of transaction is listening, 'filter' has to have a 'sender' value @@ -122,6 +130,16 @@ export interface TransactionListenerInterface { */ stop: () => void + /** + * start() method starts the corresponding listener of the instance it's called from. + */ + start: () => void + + /** + * getStatus() method returns the status of the listener. + */ + getStatus: () => boolean + /** * on() method is a listener that listens to the transaction events. * When a transaction is detected, it triggers the event. From 832ac42d13a170559d912c2aecc4d06e3915c1dd Mon Sep 17 00:00:00 2001 From: Halil Beycan <50718965+BeycanDeveloper@users.noreply.github.com> Date: Sun, 31 Mar 2024 11:10:35 +0800 Subject: [PATCH 059/114] updated --- packages/networks/boilerplate/package.json | 2 +- packages/networks/boilerplate/pnpm-lock.yaml | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/networks/boilerplate/package.json b/packages/networks/boilerplate/package.json index c833c5b..c458472 100644 --- a/packages/networks/boilerplate/package.json +++ b/packages/networks/boilerplate/package.json @@ -36,7 +36,7 @@ "url": "https://github.com/MultipleChain/js/issues" }, "dependencies": { - "@multiplechain/types": "^0.1.27", + "@multiplechain/types": "^0.1.28", "@multiplechain/utils": "^0.1.8" } } \ No newline at end of file diff --git a/packages/networks/boilerplate/pnpm-lock.yaml b/packages/networks/boilerplate/pnpm-lock.yaml index 75818cf..16a743a 100644 --- a/packages/networks/boilerplate/pnpm-lock.yaml +++ b/packages/networks/boilerplate/pnpm-lock.yaml @@ -6,16 +6,16 @@ settings: dependencies: '@multiplechain/types': - specifier: ^0.1.27 - version: 0.1.27 + specifier: ^0.1.28 + version: 0.1.28 '@multiplechain/utils': specifier: ^0.1.8 version: 0.1.9 packages: - /@multiplechain/types@0.1.27: - resolution: {integrity: sha512-lVQHp8j6rBMPwnkFLK0UsG6hL+v1ECSQc+XVkI/hdvvFfM6H4vqVTwzgHtq4UASONrEbqqbg4S52XDfV/ek7MA==} + /@multiplechain/types@0.1.28: + resolution: {integrity: sha512-PfJxzePdwvUdoQtu8Izrzv6D9ZFpPcqPrNvPG0PFBd6HwVvI+V1MrtM4d2A0KIWChDS+6W3SiVlAPBVgzbRV9A==} dev: false /@multiplechain/utils@0.1.9: From 6a6e4327e9986507727aa9781e6377028df923eb Mon Sep 17 00:00:00 2001 From: Halil Beycan <50718965+BeycanDeveloper@users.noreply.github.com> Date: Sun, 31 Mar 2024 11:11:12 +0800 Subject: [PATCH 060/114] listener generalProcess done --- packages/networks/evm-chains/package.json | 2 +- packages/networks/evm-chains/pnpm-lock.yaml | 8 +- .../evm-chains/src/models/Transaction.ts | 2 +- .../evm-chains/src/services/Ethers.ts | 8 +- .../src/services/TransactionListener.ts | 94 +++++++++++++++++-- .../networks/evm-chains/tests/models.spec.ts | 4 +- packages/networks/evm-chains/tests/setup.ts | 4 +- 7 files changed, 101 insertions(+), 21 deletions(-) diff --git a/packages/networks/evm-chains/package.json b/packages/networks/evm-chains/package.json index bdf0f62..b01df05 100644 --- a/packages/networks/evm-chains/package.json +++ b/packages/networks/evm-chains/package.json @@ -38,7 +38,7 @@ "url": "https://github.com/MultipleChain/js/issues" }, "dependencies": { - "@multiplechain/types": "^0.1.27", + "@multiplechain/types": "^0.1.28", "@multiplechain/utils": "^0.1.9", "ethers": "^6.11.1" } diff --git a/packages/networks/evm-chains/pnpm-lock.yaml b/packages/networks/evm-chains/pnpm-lock.yaml index 5021489..82af347 100644 --- a/packages/networks/evm-chains/pnpm-lock.yaml +++ b/packages/networks/evm-chains/pnpm-lock.yaml @@ -6,8 +6,8 @@ settings: dependencies: '@multiplechain/types': - specifier: ^0.1.27 - version: 0.1.27 + specifier: ^0.1.28 + version: 0.1.28 '@multiplechain/utils': specifier: ^0.1.9 version: 0.1.9 @@ -21,8 +21,8 @@ packages: resolution: {integrity: sha512-96Z2IP3mYmF1Xg2cDm8f1gWGf/HUVedQ3FMifV4kG/PQ4yEP51xDtRAEfhVNt5f/uzpNkZHwWQuUcu6D6K+Ekw==} dev: false - /@multiplechain/types@0.1.27: - resolution: {integrity: sha512-lVQHp8j6rBMPwnkFLK0UsG6hL+v1ECSQc+XVkI/hdvvFfM6H4vqVTwzgHtq4UASONrEbqqbg4S52XDfV/ek7MA==} + /@multiplechain/types@0.1.28: + resolution: {integrity: sha512-PfJxzePdwvUdoQtu8Izrzv6D9ZFpPcqPrNvPG0PFBd6HwVvI+V1MrtM4d2A0KIWChDS+6W3SiVlAPBVgzbRV9A==} dev: false /@multiplechain/utils@0.1.9: diff --git a/packages/networks/evm-chains/src/models/Transaction.ts b/packages/networks/evm-chains/src/models/Transaction.ts index 5b31158..15117ed 100644 --- a/packages/networks/evm-chains/src/models/Transaction.ts +++ b/packages/networks/evm-chains/src/models/Transaction.ts @@ -82,7 +82,7 @@ export class Transaction implements TransactionInterface { reject(TransactionStatusEnum.FAILED) } } - check() // eslint-disable-line @typescript-eslint/no-floating-promises + void check() }) } diff --git a/packages/networks/evm-chains/src/services/Ethers.ts b/packages/networks/evm-chains/src/services/Ethers.ts index 33abb4a..2b95527 100644 --- a/packages/networks/evm-chains/src/services/Ethers.ts +++ b/packages/networks/evm-chains/src/services/Ethers.ts @@ -23,7 +23,7 @@ export class Ethers { jsonRpcProvider: JsonRpcProvider - websocketProvider?: WebSocketProvider + webSocketProvider?: WebSocketProvider /** * @param {EvmNetworkConfigInterface} network @@ -32,7 +32,7 @@ export class Ethers { this.network = network this.jsonRpcProvider = new JsonRpcProvider(network.rpcUrl) if (network.wsUrl !== undefined) { - this.websocketProvider = new WebSocketProvider(network.wsUrl) + this.webSocketProvider = new WebSocketProvider(network.wsUrl) } } @@ -40,8 +40,8 @@ export class Ethers { return this.jsonRpcProvider } - public get websocket(): WebSocketProvider | undefined { - return this.websocketProvider + public get webSocket(): WebSocketProvider | undefined { + return this.webSocketProvider } /** diff --git a/packages/networks/evm-chains/src/services/TransactionListener.ts b/packages/networks/evm-chains/src/services/TransactionListener.ts index 1be059d..1774cec 100644 --- a/packages/networks/evm-chains/src/services/TransactionListener.ts +++ b/packages/networks/evm-chains/src/services/TransactionListener.ts @@ -6,6 +6,10 @@ import type { DynamicTransactionListenerFilterType } from '@multiplechain/types' +import { Provider } from './Provider.ts' +import type { Ethers } from './Ethers.ts' +import { Transaction } from '../models/Transaction.ts' +import type { WebSocketProvider, JsonRpcApiProvider } from 'ethers' import { TransactionListenerProcessIndex } from '@multiplechain/types' export class TransactionListener @@ -24,24 +28,83 @@ export class TransactionListener /** * Transaction listener filter */ - filter: DynamicTransactionListenerFilterType + filter?: DynamicTransactionListenerFilterType + + /** + * Provider + */ + provider: Provider + + /** + * Listener status + */ + status: boolean = false + + /** + * JSON-RPC provider + */ + ethers: Ethers + + /** + * JSON-RPC provider + */ + jsonRpc: JsonRpcApiProvider + + /** + * WebSocket provider + */ + webSocket: WebSocketProvider + + /** + * Dynamic stop method + */ + dynamicStop: () => void = () => {} /** * @param type - Transaction type * @param filter - Transaction listener filter */ - constructor(type: T, filter: DynamicTransactionListenerFilterType) { + constructor(type: T, filter?: DynamicTransactionListenerFilterType, provider?: Provider) { this.type = type this.filter = filter - // @ts-expect-error allow dynamic access - this[TransactionListenerProcessIndex[type]]() + this.provider = provider ?? Provider.instance + this.ethers = this.provider.ethers + this.jsonRpc = this.provider.ethers.jsonRpc + // Check if the WebSocket URL is defined + if (this.provider.ethers.webSocket === undefined) { + throw new Error('WebSocket URL is not defined') + } else { + this.webSocket = this.provider.ethers.webSocket + } } /** * Close the listener */ stop(): void { - // Close the listener + if (this.status) { + this.status = false + this.dynamicStop() + } + } + + /** + * Start the listener + */ + start(): void { + if (!this.status) { + this.status = true + // @ts-expect-error allow dynamic access + this[TransactionListenerProcessIndex[this.type]]() + } + } + + /** + * Get the listener status + * @returns - Listener status + */ + getStatus(): boolean { + return this.status } /** @@ -49,6 +112,7 @@ export class TransactionListener * @param callback - Callback function */ on(callback: TransactionListenerCallbackType): void { + this.start() this.callbacks.push(callback) } @@ -56,7 +120,7 @@ export class TransactionListener * Trigger the event when a transaction is detected * @param transaction - Transaction data */ - trigger(transaction: DynamicTransactionType): void { + trigger(transaction: DynamicTransactionType): void { this.callbacks.forEach((callback) => { callback(transaction) }) @@ -66,7 +130,23 @@ export class TransactionListener * General transaction process */ generalProcess(): void { - // General transaction process + const callback = async (transactionId: string): Promise => { + if (this.filter?.signer === undefined) { + this.trigger(new Transaction(transactionId)) + } else { + const transaction = await this.ethers.getTransaction(transactionId) + if ( + transaction !== null && + transaction.from.toLowerCase() === this.filter.signer.toLowerCase() + ) { + this.trigger(new Transaction(transactionId)) + } + } + } + void this.webSocket.on('pending', callback) + this.dynamicStop = () => { + void this.webSocket.off('pending', callback) + } } /** diff --git a/packages/networks/evm-chains/tests/models.spec.ts b/packages/networks/evm-chains/tests/models.spec.ts index 8294fa9..753478d 100644 --- a/packages/networks/evm-chains/tests/models.spec.ts +++ b/packages/networks/evm-chains/tests/models.spec.ts @@ -42,7 +42,7 @@ describe('Transaction', () => { }) it('Sender', async () => { - expect(await tx.getSender()).toBe(coinSender) + expect(await tx.getSigner()).toBe(coinSender) }) it('Fee', async () => { @@ -142,7 +142,7 @@ describe('NFT Transaction', () => { }) it('From', async () => { - expect((await tx.getFrom()).toLowerCase()).toBe(nftSender.toLowerCase()) + expect((await tx.getSender()).toLowerCase()).toBe(nftSender.toLowerCase()) }) it('Sender', async () => { diff --git a/packages/networks/evm-chains/tests/setup.ts b/packages/networks/evm-chains/tests/setup.ts index 74c5dc0..3aa18e1 100644 --- a/packages/networks/evm-chains/tests/setup.ts +++ b/packages/networks/evm-chains/tests/setup.ts @@ -5,8 +5,8 @@ export const provider = new Provider({ hexId: '0xaa36a7', mainnetId: 1, name: 'Ethereum Sepolia Testnet (QR)', - rpcUrl: 'https://dimensional-icy-tent.ethereum-sepolia.quiknode.pro/e6a31d965b3ab5fc57d5980d187121f1894c0eb4/', - wsUrl: 'wss://dimensional-icy-tent.ethereum-sepolia.quiknode.pro/e6a31d965b3ab5fc57d5980d187121f1894c0eb4/', + rpcUrl: 'https://sepolia.infura.io/v3/9aa3d95b3bc440fa88ea12eaa4456161', + wsUrl: 'wss://sepolia.infura.io/ws/v3/9aa3d95b3bc440fa88ea12eaa4456161', explorerUrl: 'https://sepolia.etherscan.io/', nativeCurrency: { symbol: 'ETH', From 02b363837ca771ca3102442d1e895a0c9d014c64 Mon Sep 17 00:00:00 2001 From: Halil Beycan <50718965+BeycanDeveloper@users.noreply.github.com> Date: Sun, 31 Mar 2024 11:12:33 +0800 Subject: [PATCH 061/114] ignore test* files --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index f88a2dd..fa2a173 100644 --- a/.gitignore +++ b/.gitignore @@ -13,6 +13,8 @@ dist dist-ssr *.local index.html +test*.ts +test*.js # Editor directories and files .vscode/* From 3f6f6bd3c5eacaf922840732e6aa62238dd77b25 Mon Sep 17 00:00:00 2001 From: Halil Beycan <50718965+BeycanDeveloper@users.noreply.github.com> Date: Sun, 31 Mar 2024 13:53:13 +0800 Subject: [PATCH 062/114] contractProcess done --- .../evm-chains/src/services/Ethers.ts | 27 +++++++++---- .../src/services/TransactionListener.ts | 40 ++++++++++++++++--- 2 files changed, 55 insertions(+), 12 deletions(-) diff --git a/packages/networks/evm-chains/src/services/Ethers.ts b/packages/networks/evm-chains/src/services/Ethers.ts index 2b95527..da4cd2f 100644 --- a/packages/networks/evm-chains/src/services/Ethers.ts +++ b/packages/networks/evm-chains/src/services/Ethers.ts @@ -1,6 +1,7 @@ import type { Block, BlockTag, + EthersError, JsonRpcSigner, TransactionReceipt, TransactionResponse @@ -8,16 +9,10 @@ import type { import { Wallet, Contract, ContractFactory, JsonRpcProvider, WebSocketProvider } from 'ethers' +import { sleep } from '@multiplechain/utils' import type { EvmNetworkConfigInterface } from './Provider.ts' import type { TransactionData } from '../services/TransactionSigner.ts' -export interface EthersError { - shortMessage: string - code: string - value: string - args: string -} - export class Ethers { network: EvmNetworkConfigInterface @@ -81,6 +76,24 @@ export class Ethers { return new ContractFactory(abi, bytecode, signer) } + /** + * @param {string} address + * @returns {Promise} + */ + async getByteCode(address: string): Promise { + try { + return await this.jsonRpc.getCode(address) + } catch (error) { + const e = error as EthersError + if (e.code === 'UNCONFIGURED_NAME') { + await sleep(1000) + return await this.getByteCode(address) + } else { + throw error + } + } + } + /** * @param {Object} data * @returns {Promise} diff --git a/packages/networks/evm-chains/src/services/TransactionListener.ts b/packages/networks/evm-chains/src/services/TransactionListener.ts index 1774cec..4b38255 100644 --- a/packages/networks/evm-chains/src/services/TransactionListener.ts +++ b/packages/networks/evm-chains/src/services/TransactionListener.ts @@ -135,10 +135,7 @@ export class TransactionListener this.trigger(new Transaction(transactionId)) } else { const transaction = await this.ethers.getTransaction(transactionId) - if ( - transaction !== null && - transaction.from.toLowerCase() === this.filter.signer.toLowerCase() - ) { + if (transaction?.from.toLowerCase() === this.filter.signer.toLowerCase()) { this.trigger(new Transaction(transactionId)) } } @@ -153,7 +150,40 @@ export class TransactionListener * Contract transaction process */ contractProcess(): void { - // Contract transaction process + const filter = this + .filter as DynamicTransactionListenerFilterType + + const callback = async (transactionId: string): Promise => { + const transaction = await this.ethers.getTransaction(transactionId) + const contractBytecode = await this.ethers.getByteCode(transaction?.to ?? '') + + if (contractBytecode === '0x' || transaction === null) { + return + } + + if (filter.address !== undefined && filter.signer !== undefined) { + if ( + transaction.from.toLowerCase() === filter.signer.toLowerCase() && + transaction.to?.toLowerCase() === filter.address.toLowerCase() + ) { + this.trigger(new Transaction(transactionId)) + } + } else if (filter.address !== undefined) { + if (transaction.to?.toLowerCase() === filter.address.toLowerCase()) { + this.trigger(new Transaction(transactionId)) + } + } else if (filter.signer !== undefined) { + if (transaction.from.toLowerCase() === filter.signer.toLowerCase()) { + this.trigger(new Transaction(transactionId)) + } + } else { + this.trigger(new Transaction(transactionId)) + } + } + void this.webSocket.on('pending', callback) + this.dynamicStop = () => { + void this.webSocket.off('pending', callback) + } } /** From 2cb8fee6c396ffd967c7b9f7b3f267016264b670 Mon Sep 17 00:00:00 2001 From: Halil Beycan <50718965+BeycanDeveloper@users.noreply.github.com> Date: Sun, 31 Mar 2024 14:53:50 +0800 Subject: [PATCH 063/114] removed direction in listener asset filter --- packages/types/package.json | 2 +- .../types/src/services/TransactionListenerInterface.ts | 8 +++----- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/packages/types/package.json b/packages/types/package.json index 6412dc2..2a87d94 100644 --- a/packages/types/package.json +++ b/packages/types/package.json @@ -1,6 +1,6 @@ { "name": "@multiplechain/types", - "version": "0.1.28", + "version": "0.1.29", "type": "module", "main": "./src/index.ts", "types": "./src/index.ts", diff --git a/packages/types/src/services/TransactionListenerInterface.ts b/packages/types/src/services/TransactionListenerInterface.ts index 656339d..c05757f 100644 --- a/packages/types/src/services/TransactionListenerInterface.ts +++ b/packages/types/src/services/TransactionListenerInterface.ts @@ -7,7 +7,6 @@ import type { } from '../models.ts' import { TransactionTypeEnum } from '../enums.ts' -import type { AssetDirectionEnum } from '../enums.ts' /** * Filter types for each transaction type in TransactionListenerInterface @@ -17,17 +16,16 @@ interface TransactionListenerFilterInterface { } interface ContractTransactionListenerFilterInterface extends TransactionListenerFilterInterface { - address?: string + address: string } interface AssetTransactionListenerFilterInterface extends TransactionListenerFilterInterface { sender?: string receiver?: string - direction?: AssetDirectionEnum } interface CoinTransactionListenerFilterInterface extends AssetTransactionListenerFilterInterface { - amount?: string + amount?: number } interface TokenTransactionListenerFilterInterface @@ -39,7 +37,7 @@ interface TokenTransactionListenerFilterInterface interface NftTransactionListenerFilterInterface extends AssetTransactionListenerFilterInterface, ContractTransactionListenerFilterInterface { - nftId?: string + nftId?: number } /** * Filter types for each transaction type in TransactionListenerInterface From f33eba1254cf1189a668822aa1b489713d31073c Mon Sep 17 00:00:00 2001 From: Halil Beycan <50718965+BeycanDeveloper@users.noreply.github.com> Date: Sun, 31 Mar 2024 14:54:53 +0800 Subject: [PATCH 064/114] updated --- packages/networks/boilerplate/package.json | 2 +- packages/networks/boilerplate/pnpm-lock.yaml | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/networks/boilerplate/package.json b/packages/networks/boilerplate/package.json index c458472..551b28b 100644 --- a/packages/networks/boilerplate/package.json +++ b/packages/networks/boilerplate/package.json @@ -36,7 +36,7 @@ "url": "https://github.com/MultipleChain/js/issues" }, "dependencies": { - "@multiplechain/types": "^0.1.28", + "@multiplechain/types": "^0.1.29", "@multiplechain/utils": "^0.1.8" } } \ No newline at end of file diff --git a/packages/networks/boilerplate/pnpm-lock.yaml b/packages/networks/boilerplate/pnpm-lock.yaml index 16a743a..fde1777 100644 --- a/packages/networks/boilerplate/pnpm-lock.yaml +++ b/packages/networks/boilerplate/pnpm-lock.yaml @@ -6,16 +6,16 @@ settings: dependencies: '@multiplechain/types': - specifier: ^0.1.28 - version: 0.1.28 + specifier: ^0.1.29 + version: 0.1.29 '@multiplechain/utils': specifier: ^0.1.8 version: 0.1.9 packages: - /@multiplechain/types@0.1.28: - resolution: {integrity: sha512-PfJxzePdwvUdoQtu8Izrzv6D9ZFpPcqPrNvPG0PFBd6HwVvI+V1MrtM4d2A0KIWChDS+6W3SiVlAPBVgzbRV9A==} + /@multiplechain/types@0.1.29: + resolution: {integrity: sha512-hp9Upb4XQyxfNHDo8o7F3MUFadxMPCuRuN44ZljwsklSNp4e4ZUWBtFIbVd5mFc1O0dkgD0SYEPthUtEgzIyoA==} dev: false /@multiplechain/utils@0.1.9: From df0694ec51cd2e3a13b11862dbf8e512b652af53 Mon Sep 17 00:00:00 2001 From: Halil Beycan <50718965+BeycanDeveloper@users.noreply.github.com> Date: Sun, 31 Mar 2024 14:56:23 +0800 Subject: [PATCH 065/114] updated --- .../src/services/TransactionListener.ts | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/packages/networks/boilerplate/src/services/TransactionListener.ts b/packages/networks/boilerplate/src/services/TransactionListener.ts index 1be059d..937d12d 100644 --- a/packages/networks/boilerplate/src/services/TransactionListener.ts +++ b/packages/networks/boilerplate/src/services/TransactionListener.ts @@ -26,6 +26,11 @@ export class TransactionListener */ filter: DynamicTransactionListenerFilterType + /** + * Listener status + */ + status: boolean + /** * @param type - Transaction type * @param filter - Transaction listener filter @@ -44,6 +49,21 @@ export class TransactionListener // Close the listener } + /** + * Start the listener + */ + start(): void { + // Start the listener + } + + /** + * Get the listener status + * @returns boolean + */ + getStatus(): boolean { + return this.status + } + /** * Listen to the transaction events * @param callback - Callback function From 496f643039516526409fa77f762d9efef0480f2b Mon Sep 17 00:00:00 2001 From: Halil Beycan <50718965+BeycanDeveloper@users.noreply.github.com> Date: Sun, 31 Mar 2024 15:25:34 +0800 Subject: [PATCH 066/114] coinProcess done --- packages/networks/evm-chains/package.json | 2 +- packages/networks/evm-chains/pnpm-lock.yaml | 8 +-- .../src/services/TransactionListener.ts | 72 +++++++++++++++++-- 3 files changed, 72 insertions(+), 10 deletions(-) diff --git a/packages/networks/evm-chains/package.json b/packages/networks/evm-chains/package.json index b01df05..77e4f5e 100644 --- a/packages/networks/evm-chains/package.json +++ b/packages/networks/evm-chains/package.json @@ -38,7 +38,7 @@ "url": "https://github.com/MultipleChain/js/issues" }, "dependencies": { - "@multiplechain/types": "^0.1.28", + "@multiplechain/types": "^0.1.29", "@multiplechain/utils": "^0.1.9", "ethers": "^6.11.1" } diff --git a/packages/networks/evm-chains/pnpm-lock.yaml b/packages/networks/evm-chains/pnpm-lock.yaml index 82af347..0118cd6 100644 --- a/packages/networks/evm-chains/pnpm-lock.yaml +++ b/packages/networks/evm-chains/pnpm-lock.yaml @@ -6,8 +6,8 @@ settings: dependencies: '@multiplechain/types': - specifier: ^0.1.28 - version: 0.1.28 + specifier: ^0.1.29 + version: 0.1.29 '@multiplechain/utils': specifier: ^0.1.9 version: 0.1.9 @@ -21,8 +21,8 @@ packages: resolution: {integrity: sha512-96Z2IP3mYmF1Xg2cDm8f1gWGf/HUVedQ3FMifV4kG/PQ4yEP51xDtRAEfhVNt5f/uzpNkZHwWQuUcu6D6K+Ekw==} dev: false - /@multiplechain/types@0.1.28: - resolution: {integrity: sha512-PfJxzePdwvUdoQtu8Izrzv6D9ZFpPcqPrNvPG0PFBd6HwVvI+V1MrtM4d2A0KIWChDS+6W3SiVlAPBVgzbRV9A==} + /@multiplechain/types@0.1.29: + resolution: {integrity: sha512-hp9Upb4XQyxfNHDo8o7F3MUFadxMPCuRuN44ZljwsklSNp4e4ZUWBtFIbVd5mFc1O0dkgD0SYEPthUtEgzIyoA==} dev: false /@multiplechain/utils@0.1.9: diff --git a/packages/networks/evm-chains/src/services/TransactionListener.ts b/packages/networks/evm-chains/src/services/TransactionListener.ts index 4b38255..d0e5f2a 100644 --- a/packages/networks/evm-chains/src/services/TransactionListener.ts +++ b/packages/networks/evm-chains/src/services/TransactionListener.ts @@ -11,6 +11,8 @@ import type { Ethers } from './Ethers.ts' import { Transaction } from '../models/Transaction.ts' import type { WebSocketProvider, JsonRpcApiProvider } from 'ethers' import { TransactionListenerProcessIndex } from '@multiplechain/types' +import { ContractTransaction } from '../models/ContractTransaction.ts' +import { CoinTransaction } from '../models/CoinTransaction.ts' export class TransactionListener implements TransactionListenerInterface @@ -140,6 +142,7 @@ export class TransactionListener } } } + void this.webSocket.on('pending', callback) this.dynamicStop = () => { void this.webSocket.off('pending', callback) @@ -166,20 +169,21 @@ export class TransactionListener transaction.from.toLowerCase() === filter.signer.toLowerCase() && transaction.to?.toLowerCase() === filter.address.toLowerCase() ) { - this.trigger(new Transaction(transactionId)) + this.trigger(new ContractTransaction(transactionId)) } } else if (filter.address !== undefined) { if (transaction.to?.toLowerCase() === filter.address.toLowerCase()) { - this.trigger(new Transaction(transactionId)) + this.trigger(new ContractTransaction(transactionId)) } } else if (filter.signer !== undefined) { if (transaction.from.toLowerCase() === filter.signer.toLowerCase()) { - this.trigger(new Transaction(transactionId)) + this.trigger(new ContractTransaction(transactionId)) } } else { - this.trigger(new Transaction(transactionId)) + this.trigger(new ContractTransaction(transactionId)) } } + void this.webSocket.on('pending', callback) this.dynamicStop = () => { void this.webSocket.off('pending', callback) @@ -190,7 +194,65 @@ export class TransactionListener * Coin transaction process */ coinProcess(): void { - // Coin transaction process + const filter = this.filter as DynamicTransactionListenerFilterType + + const callback = async (transactionId: string): Promise => { + if ( + filter.signer !== undefined && + filter.sender !== undefined && + filter.signer !== filter.sender + ) { + throw new Error( + 'Sender and signer must be the same in coin transactions. Or only one of them can be defined.' + ) + } + + const tx = await this.ethers.getTransaction(transactionId) + const contractBytecode = await this.ethers.getByteCode(tx?.to ?? '') + + if (contractBytecode !== '0x' || tx === null) { + return + } + + let transaction: CoinTransaction | undefined + const sender = filter.sender ?? filter.signer + + if (sender !== undefined && filter.receiver !== undefined) { + if ( + tx.from.toLowerCase() === sender.toLowerCase() && + tx.to?.toLowerCase() === filter.receiver.toLowerCase() + ) { + transaction = new CoinTransaction(transactionId) + } + } else if (sender !== undefined) { + if (tx.from.toLowerCase() === sender.toLowerCase()) { + transaction = new CoinTransaction(transactionId) + } + } else if (filter.receiver !== undefined) { + if (tx.to?.toLowerCase() === filter.receiver.toLowerCase()) { + transaction = new CoinTransaction(transactionId) + } + } else { + transaction = new CoinTransaction(transactionId) + } + + if (filter.amount !== undefined && transaction !== undefined) { + await transaction.wait() + const amount = await transaction.getAmount() + if (amount !== filter.amount) { + transaction = undefined + } + } + + if (transaction !== undefined) { + this.trigger(transaction) + } + } + + void this.webSocket.on('pending', callback) + this.dynamicStop = () => { + void this.webSocket.off('pending', callback) + } } /** From 969632e51b20ee970942ef2b7c5a0f8386404a65 Mon Sep 17 00:00:00 2001 From: Halil Beycan <50718965+BeycanDeveloper@users.noreply.github.com> Date: Sun, 31 Mar 2024 15:30:09 +0800 Subject: [PATCH 067/114] updated --- packages/types/package.json | 2 +- packages/types/src/services/TransactionListenerInterface.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/types/package.json b/packages/types/package.json index 2a87d94..652ff38 100644 --- a/packages/types/package.json +++ b/packages/types/package.json @@ -1,6 +1,6 @@ { "name": "@multiplechain/types", - "version": "0.1.29", + "version": "0.1.30", "type": "module", "main": "./src/index.ts", "types": "./src/index.ts", diff --git a/packages/types/src/services/TransactionListenerInterface.ts b/packages/types/src/services/TransactionListenerInterface.ts index c05757f..8fd19cc 100644 --- a/packages/types/src/services/TransactionListenerInterface.ts +++ b/packages/types/src/services/TransactionListenerInterface.ts @@ -16,7 +16,7 @@ interface TransactionListenerFilterInterface { } interface ContractTransactionListenerFilterInterface extends TransactionListenerFilterInterface { - address: string + address?: string } interface AssetTransactionListenerFilterInterface extends TransactionListenerFilterInterface { From bd84da01cdd105393229f124017ef71b7943f4ec Mon Sep 17 00:00:00 2001 From: Halil Beycan <50718965+BeycanDeveloper@users.noreply.github.com> Date: Sun, 31 Mar 2024 15:30:34 +0800 Subject: [PATCH 068/114] updated --- packages/networks/boilerplate/package.json | 2 +- packages/networks/boilerplate/pnpm-lock.yaml | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/networks/boilerplate/package.json b/packages/networks/boilerplate/package.json index 551b28b..9871563 100644 --- a/packages/networks/boilerplate/package.json +++ b/packages/networks/boilerplate/package.json @@ -36,7 +36,7 @@ "url": "https://github.com/MultipleChain/js/issues" }, "dependencies": { - "@multiplechain/types": "^0.1.29", + "@multiplechain/types": "^0.1.30", "@multiplechain/utils": "^0.1.8" } } \ No newline at end of file diff --git a/packages/networks/boilerplate/pnpm-lock.yaml b/packages/networks/boilerplate/pnpm-lock.yaml index fde1777..108f977 100644 --- a/packages/networks/boilerplate/pnpm-lock.yaml +++ b/packages/networks/boilerplate/pnpm-lock.yaml @@ -6,16 +6,16 @@ settings: dependencies: '@multiplechain/types': - specifier: ^0.1.29 - version: 0.1.29 + specifier: ^0.1.30 + version: 0.1.30 '@multiplechain/utils': specifier: ^0.1.8 version: 0.1.9 packages: - /@multiplechain/types@0.1.29: - resolution: {integrity: sha512-hp9Upb4XQyxfNHDo8o7F3MUFadxMPCuRuN44ZljwsklSNp4e4ZUWBtFIbVd5mFc1O0dkgD0SYEPthUtEgzIyoA==} + /@multiplechain/types@0.1.30: + resolution: {integrity: sha512-j72Ydn1FlEWF4lY6xUjI0ojf0y1JAjqYnddAaUUdzv5sRlFw2zze8VLqxzltFtjFigPbSUa7QHmbgTIXQ60HoQ==} dev: false /@multiplechain/utils@0.1.9: From f59e476c73eacb0bfef51aac0ec18a9fc815d79d Mon Sep 17 00:00:00 2001 From: Halil Beycan <50718965+BeycanDeveloper@users.noreply.github.com> Date: Sun, 31 Mar 2024 17:36:54 +0800 Subject: [PATCH 069/114] added objectsEqual method --- packages/utils/package.json | 2 +- packages/utils/src/index.ts | 21 +++++++++++++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/packages/utils/package.json b/packages/utils/package.json index 5b6b3e5..a835704 100644 --- a/packages/utils/package.json +++ b/packages/utils/package.json @@ -1,6 +1,6 @@ { "name": "@multiplechain/utils", - "version": "0.1.9", + "version": "0.1.10", "type": "module", "main": "./src/index.ts", "types": "./src/index.ts", diff --git a/packages/utils/src/index.ts b/packages/utils/src/index.ts index 20e9de7..1bac426 100644 --- a/packages/utils/src/index.ts +++ b/packages/utils/src/index.ts @@ -106,12 +106,33 @@ export const getDecimalPlaces = (num: number): number => { } } +/** + * Fix the float number + * @param {number} num + * @returns number + * @example 1.0000000000000001 => 1 + */ export const fixFloat = (num: number): number => { return parseFloat(num.toFixed(getDecimalPlaces(num))) } +/** + * Sleeps the given milliseconds + * @param {number} ms + * @returns Promise + */ export const sleep = async (ms: number): Promise => { await new Promise((resolve) => setTimeout(resolve, ms)) } +/** + * Checks if the given objects are equal + * @param {any} o1 + * @param {any} o2 + * @returns boolean + */ +export const objectsEqual = (o1: any, o2: any): boolean => { + return JSON.stringify(o1) === JSON.stringify(o2) +} + export { toHex } From a22077898f51c27aa846f96cd92546184091c922 Mon Sep 17 00:00:00 2001 From: Halil Beycan <50718965+BeycanDeveloper@users.noreply.github.com> Date: Sun, 31 Mar 2024 17:37:44 +0800 Subject: [PATCH 070/114] updated --- packages/networks/boilerplate/package.json | 2 +- packages/networks/boilerplate/pnpm-lock.yaml | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/networks/boilerplate/package.json b/packages/networks/boilerplate/package.json index 9871563..03ba2b6 100644 --- a/packages/networks/boilerplate/package.json +++ b/packages/networks/boilerplate/package.json @@ -37,6 +37,6 @@ }, "dependencies": { "@multiplechain/types": "^0.1.30", - "@multiplechain/utils": "^0.1.8" + "@multiplechain/utils": "^0.1.10" } } \ No newline at end of file diff --git a/packages/networks/boilerplate/pnpm-lock.yaml b/packages/networks/boilerplate/pnpm-lock.yaml index 108f977..a13694b 100644 --- a/packages/networks/boilerplate/pnpm-lock.yaml +++ b/packages/networks/boilerplate/pnpm-lock.yaml @@ -9,8 +9,8 @@ dependencies: specifier: ^0.1.30 version: 0.1.30 '@multiplechain/utils': - specifier: ^0.1.8 - version: 0.1.9 + specifier: ^0.1.10 + version: 0.1.10 packages: @@ -18,8 +18,8 @@ packages: resolution: {integrity: sha512-j72Ydn1FlEWF4lY6xUjI0ojf0y1JAjqYnddAaUUdzv5sRlFw2zze8VLqxzltFtjFigPbSUa7QHmbgTIXQ60HoQ==} dev: false - /@multiplechain/utils@0.1.9: - resolution: {integrity: sha512-52yrmloGDwXrMwOSfEiPJfePPIDeEqGMTE4u5QE2BQPdGe0Bto908pX4IIF1j0Srmv5TJdH9JN3MFEgzgo3qAw==} + /@multiplechain/utils@0.1.10: + resolution: {integrity: sha512-Ed0YxvRakds1WiREcLWI+fr6YCNB3bSORPD/ZQNqhELtL5uVgYWunIwbx6yZmLNk4MY8Qqyh0iUjuCOBLplmiA==} dependencies: bignumber.js: 9.1.2 web3-utils: 4.2.1 From c40b788029e8cb5cb72e18ae9b5e5ba5b91d1cfe Mon Sep 17 00:00:00 2001 From: Halil Beycan <50718965+BeycanDeveloper@users.noreply.github.com> Date: Sun, 31 Mar 2024 17:58:13 +0800 Subject: [PATCH 071/114] tokenProcess done --- packages/networks/evm-chains/package.json | 4 +- packages/networks/evm-chains/pnpm-lock.yaml | 16 +- .../src/models/ContractTransaction.ts | 22 ++- .../evm-chains/src/models/NftTransaction.ts | 15 +- .../evm-chains/src/models/TokenTransaction.ts | 17 +- .../evm-chains/src/models/Transaction.ts | 11 +- .../evm-chains/src/services/Ethers.ts | 2 + .../src/services/TransactionListener.ts | 183 +++++++++++++----- .../networks/evm-chains/tests/models.spec.ts | 6 +- packages/networks/evm-chains/tests/setup.ts | 2 + 10 files changed, 196 insertions(+), 82 deletions(-) diff --git a/packages/networks/evm-chains/package.json b/packages/networks/evm-chains/package.json index 77e4f5e..6789218 100644 --- a/packages/networks/evm-chains/package.json +++ b/packages/networks/evm-chains/package.json @@ -38,8 +38,8 @@ "url": "https://github.com/MultipleChain/js/issues" }, "dependencies": { - "@multiplechain/types": "^0.1.29", - "@multiplechain/utils": "^0.1.9", + "@multiplechain/types": "^0.1.30", + "@multiplechain/utils": "^0.1.10", "ethers": "^6.11.1" } } \ No newline at end of file diff --git a/packages/networks/evm-chains/pnpm-lock.yaml b/packages/networks/evm-chains/pnpm-lock.yaml index 0118cd6..f01cc5b 100644 --- a/packages/networks/evm-chains/pnpm-lock.yaml +++ b/packages/networks/evm-chains/pnpm-lock.yaml @@ -6,11 +6,11 @@ settings: dependencies: '@multiplechain/types': - specifier: ^0.1.29 - version: 0.1.29 + specifier: ^0.1.30 + version: 0.1.30 '@multiplechain/utils': - specifier: ^0.1.9 - version: 0.1.9 + specifier: ^0.1.10 + version: 0.1.10 ethers: specifier: ^6.11.1 version: 6.11.1 @@ -21,12 +21,12 @@ packages: resolution: {integrity: sha512-96Z2IP3mYmF1Xg2cDm8f1gWGf/HUVedQ3FMifV4kG/PQ4yEP51xDtRAEfhVNt5f/uzpNkZHwWQuUcu6D6K+Ekw==} dev: false - /@multiplechain/types@0.1.29: - resolution: {integrity: sha512-hp9Upb4XQyxfNHDo8o7F3MUFadxMPCuRuN44ZljwsklSNp4e4ZUWBtFIbVd5mFc1O0dkgD0SYEPthUtEgzIyoA==} + /@multiplechain/types@0.1.30: + resolution: {integrity: sha512-j72Ydn1FlEWF4lY6xUjI0ojf0y1JAjqYnddAaUUdzv5sRlFw2zze8VLqxzltFtjFigPbSUa7QHmbgTIXQ60HoQ==} dev: false - /@multiplechain/utils@0.1.9: - resolution: {integrity: sha512-52yrmloGDwXrMwOSfEiPJfePPIDeEqGMTE4u5QE2BQPdGe0Bto908pX4IIF1j0Srmv5TJdH9JN3MFEgzgo3qAw==} + /@multiplechain/utils@0.1.10: + resolution: {integrity: sha512-Ed0YxvRakds1WiREcLWI+fr6YCNB3bSORPD/ZQNqhELtL5uVgYWunIwbx6yZmLNk4MY8Qqyh0iUjuCOBLplmiA==} dependencies: bignumber.js: 9.1.2 web3-utils: 4.2.2 diff --git a/packages/networks/evm-chains/src/models/ContractTransaction.ts b/packages/networks/evm-chains/src/models/ContractTransaction.ts index f09585c..31c5a9e 100644 --- a/packages/networks/evm-chains/src/models/ContractTransaction.ts +++ b/packages/networks/evm-chains/src/models/ContractTransaction.ts @@ -1,6 +1,6 @@ import { Transaction } from './Transaction.ts' -import { Interface, type TransactionDescription } from 'ethers' import type { ContractTransactionInterface } from '@multiplechain/types' +import { Interface, type TransactionDescription, type TransactionResponse } from 'ethers' export class ContractTransaction extends Transaction implements ContractTransactionInterface { /** @@ -13,15 +13,23 @@ export class ContractTransaction extends Transaction implements ContractTransact /** * @param {object[]} abiArray - * @returns {Promise} + * @param {TransactionResponse} response + * @returns {Promise} */ - async decodeData(abiArray: object[]): Promise { - const data = await this.getData() - if (data === null) return null + async decodeDataBase( + abiArray: object[], + response?: TransactionResponse + ): Promise { + if (response === undefined) { + const data = await this.getData() + if (data === null) return null + response = data.response + } + const iface = new Interface(abiArray) return iface.parseTransaction({ - data: data?.response.data ?? '', - value: data?.response.value ?? 0 + data: response.data ?? '', + value: response.value ?? 0 }) } } diff --git a/packages/networks/evm-chains/src/models/NftTransaction.ts b/packages/networks/evm-chains/src/models/NftTransaction.ts index 5b87a09..c642065 100644 --- a/packages/networks/evm-chains/src/models/NftTransaction.ts +++ b/packages/networks/evm-chains/src/models/NftTransaction.ts @@ -1,14 +1,23 @@ import ERC721 from '../../resources/erc721.json' import { ContractTransaction } from './ContractTransaction.ts' import type { NftTransactionInterface } from '@multiplechain/types' +import type { TransactionDescription, TransactionResponse } from 'ethers' import { TransactionStatusEnum, AssetDirectionEnum } from '@multiplechain/types' export class NftTransaction extends ContractTransaction implements NftTransactionInterface { + /** + * @param {TransactionResponse} response + * @returns {Promise} + */ + async decodeData(response?: TransactionResponse): Promise { + return await super.decodeDataBase(ERC721, response) + } + /** * @returns Wallet address of the sender of transaction */ async getReceiver(): Promise { - const decoded = await this.decodeData(ERC721) + const decoded = await this.decodeData() if (decoded === null) { return '' @@ -25,7 +34,7 @@ export class NftTransaction extends ContractTransaction implements NftTransactio * @returns Wallet address of the sender of transaction */ async getSender(): Promise { - const decoded = await this.decodeData(ERC721) + const decoded = await this.decodeData() if (decoded === null) { return '' @@ -42,7 +51,7 @@ export class NftTransaction extends ContractTransaction implements NftTransactio * @returns ID of the NFT */ async getNftId(): Promise { - return Number((await this.decodeData(ERC721))?.args[2] ?? 0) + return Number((await this.decodeData())?.args[2] ?? 0) } /** diff --git a/packages/networks/evm-chains/src/models/TokenTransaction.ts b/packages/networks/evm-chains/src/models/TokenTransaction.ts index d3a89f7..0fc193f 100644 --- a/packages/networks/evm-chains/src/models/TokenTransaction.ts +++ b/packages/networks/evm-chains/src/models/TokenTransaction.ts @@ -1,16 +1,25 @@ import { Token } from '../assets/Token.ts' import ERC20 from '../../resources/erc20.json' import { hexToNumber } from '@multiplechain/utils' -import { ContractTransaction } from './ContractTransaction.ts' import { TransactionStatusEnum } from '@multiplechain/types' +import { ContractTransaction } from './ContractTransaction.ts' +import type { TransactionDescription, TransactionResponse } from 'ethers' import { AssetDirectionEnum, type TokenTransactionInterface } from '@multiplechain/types' export class TokenTransaction extends ContractTransaction implements TokenTransactionInterface { + /** + * @param {TransactionResponse} response + * @returns {Promise} + */ + async decodeData(response?: TransactionResponse): Promise { + return await super.decodeDataBase(ERC20, response) + } + /** * @returns Wallet address of the sender of transaction */ async getReceiver(): Promise { - const decoded = await this.decodeData(ERC20) + const decoded = await this.decodeData() if (decoded === null) { return '' @@ -27,7 +36,7 @@ export class TokenTransaction extends ContractTransaction implements TokenTransa * @returns Wallet address of the sender of transaction */ async getSender(): Promise { - const decoded = await this.decodeData(ERC20) + const decoded = await this.decodeData() if (decoded === null) { return '' @@ -49,7 +58,7 @@ export class TokenTransaction extends ContractTransaction implements TokenTransa */ async getAmount(): Promise { const token = new Token(await this.getAddress()) - const decoded = await this.decodeData(ERC20) + const decoded = await this.decodeData() if (decoded === null) { return 0 } diff --git a/packages/networks/evm-chains/src/models/Transaction.ts b/packages/networks/evm-chains/src/models/Transaction.ts index 15117ed..be2a3aa 100644 --- a/packages/networks/evm-chains/src/models/Transaction.ts +++ b/packages/networks/evm-chains/src/models/Transaction.ts @@ -7,7 +7,7 @@ import { hexToNumber } from '@multiplechain/utils' interface TransactionData { response: TransactionResponse - receipt: TransactionReceipt + receipt: TransactionReceipt | null } export class Transaction implements TransactionInterface { @@ -44,7 +44,7 @@ export class Transaction implements TransactionInterface { * @returns Raw transaction data that is taken by blockchain network via RPC. */ async getData(): Promise { - if (this.data !== undefined) { + if (this.data?.response !== undefined && this.data?.receipt !== null) { return this.data } try { @@ -53,9 +53,6 @@ export class Transaction implements TransactionInterface { return null } const receipt = await this.ethers.getTransactionReceipt(this.id) - if (receipt === null) { - return null - } return (this.data = { response, receipt }) } catch (error) { if (error instanceof Error && String(error.message).includes('timeout')) { @@ -117,7 +114,7 @@ export class Transaction implements TransactionInterface { */ async getFee(): Promise { const data = await this.getData() - if (data === null) { + if (data?.response?.gasPrice === undefined || data?.receipt?.gasUsed === undefined) { return 0 } return hexToNumber( @@ -160,7 +157,7 @@ export class Transaction implements TransactionInterface { const data = await this.getData() if (data === null) { return TransactionStatusEnum.PENDING - } else if (data.response.blockNumber !== null) { + } else if (data.response.blockNumber !== null && data.receipt !== null) { if (data.receipt.status === 1) { return TransactionStatusEnum.CONFIRMED } else { diff --git a/packages/networks/evm-chains/src/services/Ethers.ts b/packages/networks/evm-chains/src/services/Ethers.ts index da4cd2f..fdd299f 100644 --- a/packages/networks/evm-chains/src/services/Ethers.ts +++ b/packages/networks/evm-chains/src/services/Ethers.ts @@ -13,6 +13,8 @@ import { sleep } from '@multiplechain/utils' import type { EvmNetworkConfigInterface } from './Provider.ts' import type { TransactionData } from '../services/TransactionSigner.ts' +export type { EthersError } from 'ethers' + export class Ethers { network: EvmNetworkConfigInterface diff --git a/packages/networks/evm-chains/src/services/TransactionListener.ts b/packages/networks/evm-chains/src/services/TransactionListener.ts index d0e5f2a..349e631 100644 --- a/packages/networks/evm-chains/src/services/TransactionListener.ts +++ b/packages/networks/evm-chains/src/services/TransactionListener.ts @@ -6,13 +6,16 @@ import type { DynamicTransactionListenerFilterType } from '@multiplechain/types' +import { id } from 'ethers' import { Provider } from './Provider.ts' import type { Ethers } from './Ethers.ts' +import { objectsEqual } from '@multiplechain/utils' import { Transaction } from '../models/Transaction.ts' -import type { WebSocketProvider, JsonRpcApiProvider } from 'ethers' +import { CoinTransaction } from '../models/CoinTransaction.ts' import { TransactionListenerProcessIndex } from '@multiplechain/types' import { ContractTransaction } from '../models/ContractTransaction.ts' -import { CoinTransaction } from '../models/CoinTransaction.ts' +import type { WebSocketProvider, JsonRpcApiProvider, EventFilter, Log } from 'ethers' +import { TokenTransaction } from '../models/TokenTransaction.ts' export class TransactionListener implements TransactionListenerInterface @@ -133,14 +136,14 @@ export class TransactionListener */ generalProcess(): void { const callback = async (transactionId: string): Promise => { - if (this.filter?.signer === undefined) { - this.trigger(new Transaction(transactionId)) - } else { + if (this.filter?.signer !== undefined) { const transaction = await this.ethers.getTransaction(transactionId) - if (transaction?.from.toLowerCase() === this.filter.signer.toLowerCase()) { - this.trigger(new Transaction(transactionId)) + if (transaction?.from.toLowerCase() !== this.filter.signer.toLowerCase()) { + return } } + + this.trigger(new Transaction(transactionId)) } void this.webSocket.on('pending', callback) @@ -164,24 +167,29 @@ export class TransactionListener return } - if (filter.address !== undefined && filter.signer !== undefined) { - if ( - transaction.from.toLowerCase() === filter.signer.toLowerCase() && - transaction.to?.toLowerCase() === filter.address.toLowerCase() - ) { - this.trigger(new ContractTransaction(transactionId)) - } - } else if (filter.address !== undefined) { - if (transaction.to?.toLowerCase() === filter.address.toLowerCase()) { - this.trigger(new ContractTransaction(transactionId)) - } - } else if (filter.signer !== undefined) { - if (transaction.from.toLowerCase() === filter.signer.toLowerCase()) { - this.trigger(new ContractTransaction(transactionId)) - } - } else { - this.trigger(new ContractTransaction(transactionId)) + interface ParamsType { + address?: string + signer?: string + } + + const expectedParams: ParamsType = {} + const receivedParams: ParamsType = {} + + if (filter.address !== undefined) { + expectedParams.address = filter.address.toLowerCase() + receivedParams.address = transaction.to?.toLowerCase() } + + if (filter.signer !== undefined) { + expectedParams.signer = filter.signer.toLowerCase() + receivedParams.signer = transaction.from.toLowerCase() + } + + if (!objectsEqual(expectedParams, receivedParams)) { + return + } + + this.trigger(new ContractTransaction(transactionId)) } void this.webSocket.on('pending', callback) @@ -214,39 +222,41 @@ export class TransactionListener return } - let transaction: CoinTransaction | undefined const sender = filter.sender ?? filter.signer - if (sender !== undefined && filter.receiver !== undefined) { - if ( - tx.from.toLowerCase() === sender.toLowerCase() && - tx.to?.toLowerCase() === filter.receiver.toLowerCase() - ) { - transaction = new CoinTransaction(transactionId) - } - } else if (sender !== undefined) { - if (tx.from.toLowerCase() === sender.toLowerCase()) { - transaction = new CoinTransaction(transactionId) - } - } else if (filter.receiver !== undefined) { - if (tx.to?.toLowerCase() === filter.receiver.toLowerCase()) { - transaction = new CoinTransaction(transactionId) - } - } else { - transaction = new CoinTransaction(transactionId) + interface ParamsType { + sender?: string + receiver?: string + } + + const expectedParams: ParamsType = {} + const receivedParams: ParamsType = {} + + if (sender !== undefined) { + expectedParams.sender = sender.toLowerCase() + receivedParams.sender = tx.from.toLowerCase() + } + + if (filter.receiver !== undefined) { + expectedParams.receiver = filter.receiver.toLowerCase() + receivedParams.receiver = tx.to?.toLowerCase() + } + + if (!objectsEqual(expectedParams, receivedParams)) { + return } - if (filter.amount !== undefined && transaction !== undefined) { + const transaction = new CoinTransaction(transactionId) + + if (filter.amount !== undefined) { await transaction.wait() const amount = await transaction.getAmount() if (amount !== filter.amount) { - transaction = undefined + return } } - if (transaction !== undefined) { - this.trigger(transaction) - } + this.trigger(transaction) } void this.webSocket.on('pending', callback) @@ -259,7 +269,84 @@ export class TransactionListener * Token transaction process */ tokenProcess(): void { - // Token transaction process + const filter = this + .filter as DynamicTransactionListenerFilterType + + const params: EventFilter = { + topics: [id('Transfer(address,address,uint256)')] + } + + if (filter.address !== undefined) { + params.address = filter.address + } + + const callback = async (transactionLog: Log): Promise => { + const transaction = new TokenTransaction(transactionLog.transactionHash) + const data = await transaction.getData() + + if (data === null) { + return + } + + const decodedData = await transaction.decodeData(data.response) + + if (decodedData === null) { + return + } + + if (decodedData.name !== 'transfer' && decodedData.name !== 'transferFrom') { + return + } + + interface ParamsType { + signer?: string + sender?: string + receiver?: string + } + + const expectedParams: ParamsType = {} + const receivedParams: ParamsType = {} + + if (filter.signer !== undefined) { + expectedParams.signer = filter.signer.toLowerCase() + receivedParams.signer = data.response.from.toLowerCase() + } + + if (filter.sender !== undefined) { + expectedParams.sender = filter.sender.toLowerCase() + receivedParams.sender = + decodedData.name === 'transfer' + ? data.response.from.toLowerCase() + : decodedData.args[0].toLowerCase() + } + + if (filter.receiver !== undefined) { + expectedParams.receiver = filter.receiver.toLowerCase() + receivedParams.receiver = + decodedData.name === 'transfer' + ? decodedData.args[0].toLowerCase() + : decodedData.args[1].toLowerCase() + } + + if (!objectsEqual(expectedParams, receivedParams)) { + return + } + + if (filter.amount !== undefined) { + await transaction.wait() + const amount = await transaction.getAmount() + if (amount !== filter.amount) { + return + } + } + + this.trigger(transaction) + } + + void this.webSocket.on(params, callback) + this.dynamicStop = () => { + void this.webSocket.off(params, callback) + } } /** diff --git a/packages/networks/evm-chains/tests/models.spec.ts b/packages/networks/evm-chains/tests/models.spec.ts index 753478d..64fb12c 100644 --- a/packages/networks/evm-chains/tests/models.spec.ts +++ b/packages/networks/evm-chains/tests/models.spec.ts @@ -141,12 +141,12 @@ describe('NFT Transaction', () => { expect((await tx.getReceiver()).toLowerCase()).toBe(nftReceiver.toLowerCase()) }) - it('From', async () => { - expect((await tx.getSender()).toLowerCase()).toBe(nftSender.toLowerCase()) + it('Signer', async () => { + expect((await tx.getSigner()).toLowerCase()).toBe(nftReceiver.toLowerCase()) }) it('Sender', async () => { - expect((await tx.getSender()).toLowerCase()).toBe(nftReceiver.toLowerCase()) + expect((await tx.getSender()).toLowerCase()).toBe(nftSender.toLowerCase()) }) it('NFT ID', async () => { diff --git a/packages/networks/evm-chains/tests/setup.ts b/packages/networks/evm-chains/tests/setup.ts index 3aa18e1..29541ac 100644 --- a/packages/networks/evm-chains/tests/setup.ts +++ b/packages/networks/evm-chains/tests/setup.ts @@ -7,6 +7,8 @@ export const provider = new Provider({ name: 'Ethereum Sepolia Testnet (QR)', rpcUrl: 'https://sepolia.infura.io/v3/9aa3d95b3bc440fa88ea12eaa4456161', wsUrl: 'wss://sepolia.infura.io/ws/v3/9aa3d95b3bc440fa88ea12eaa4456161', + // rpcUrl: 'https://dimensional-icy-tent.ethereum-sepolia.quiknode.pro/e6a31d965b3ab5fc57d5980d187121f1894c0eb4/', + // wsUrl: 'wss://dimensional-icy-tent.ethereum-sepolia.quiknode.pro/e6a31d965b3ab5fc57d5980d187121f1894c0eb4/', explorerUrl: 'https://sepolia.etherscan.io/', nativeCurrency: { symbol: 'ETH', From 25cbe05d43755239ec84af709c675eb033185325 Mon Sep 17 00:00:00 2001 From: Halil Beycan <50718965+BeycanDeveloper@users.noreply.github.com> Date: Sun, 31 Mar 2024 18:17:24 +0800 Subject: [PATCH 072/114] added custom ABI option --- .../evm-chains/src/assets/Contract.ts | 10 +++---- .../src/models/ContractTransaction.ts | 30 ++++++++++++++----- .../evm-chains/src/models/NftTransaction.ts | 12 ++++++-- .../evm-chains/src/models/TokenTransaction.ts | 12 ++++++-- 4 files changed, 47 insertions(+), 17 deletions(-) diff --git a/packages/networks/evm-chains/src/assets/Contract.ts b/packages/networks/evm-chains/src/assets/Contract.ts index ab750c1..e7fbefd 100644 --- a/packages/networks/evm-chains/src/assets/Contract.ts +++ b/packages/networks/evm-chains/src/assets/Contract.ts @@ -11,7 +11,7 @@ export class Contract implements ContractInterface { /** * Contract ABI */ - abi: object[] + ABI: object[] /** * Ethers contract @@ -20,13 +20,13 @@ export class Contract implements ContractInterface { /** * @param address Contract address - * @param abi Contract ABI + * @param ABIArray Contract ABI */ - constructor(address: string, abi: object[]) { - this.abi = abi + constructor(address: string, ABI: object[]) { + this.ABI = ABI this.address = address const { ethers } = Provider.instance - this.ethersContract = ethers.contract(address, abi, ethers.jsonRpc) + this.ethersContract = ethers.contract(address, ABI, ethers.jsonRpc) } /** diff --git a/packages/networks/evm-chains/src/models/ContractTransaction.ts b/packages/networks/evm-chains/src/models/ContractTransaction.ts index 31c5a9e..60d6b00 100644 --- a/packages/networks/evm-chains/src/models/ContractTransaction.ts +++ b/packages/networks/evm-chains/src/models/ContractTransaction.ts @@ -1,8 +1,27 @@ import { Transaction } from './Transaction.ts' import type { ContractTransactionInterface } from '@multiplechain/types' -import { Interface, type TransactionDescription, type TransactionResponse } from 'ethers' +import { + Interface, + type InterfaceAbi, + type TransactionResponse, + type TransactionDescription +} from 'ethers' export class ContractTransaction extends Transaction implements ContractTransactionInterface { + /** + * @type {InterfaceAbi} + */ + ABI: InterfaceAbi + + /** + * @param {string} hash + * @param {InterfaceAbi} ABI + */ + constructor(hash: string, ABI: InterfaceAbi = []) { + super(hash) + this.ABI = ABI + } + /** * @returns {Promise} */ @@ -12,22 +31,17 @@ export class ContractTransaction extends Transaction implements ContractTransact } /** - * @param {object[]} abiArray * @param {TransactionResponse} response * @returns {Promise} */ - async decodeDataBase( - abiArray: object[], - response?: TransactionResponse - ): Promise { + async decodeData(response?: TransactionResponse): Promise { if (response === undefined) { const data = await this.getData() if (data === null) return null response = data.response } - const iface = new Interface(abiArray) - return iface.parseTransaction({ + return new Interface(this.ABI).parseTransaction({ data: response.data ?? '', value: response.value ?? 0 }) diff --git a/packages/networks/evm-chains/src/models/NftTransaction.ts b/packages/networks/evm-chains/src/models/NftTransaction.ts index c642065..9e010c8 100644 --- a/packages/networks/evm-chains/src/models/NftTransaction.ts +++ b/packages/networks/evm-chains/src/models/NftTransaction.ts @@ -1,16 +1,24 @@ import ERC721 from '../../resources/erc721.json' import { ContractTransaction } from './ContractTransaction.ts' import type { NftTransactionInterface } from '@multiplechain/types' -import type { TransactionDescription, TransactionResponse } from 'ethers' import { TransactionStatusEnum, AssetDirectionEnum } from '@multiplechain/types' +import type { TransactionDescription, TransactionResponse, InterfaceAbi } from 'ethers' export class NftTransaction extends ContractTransaction implements NftTransactionInterface { + /** + * @param {string} hash + * @param {InterfaceAbi} ABI + */ + constructor(hash: string, ABI?: InterfaceAbi) { + super(hash, ABI ?? ERC721) + } + /** * @param {TransactionResponse} response * @returns {Promise} */ async decodeData(response?: TransactionResponse): Promise { - return await super.decodeDataBase(ERC721, response) + return await super.decodeData(response) } /** diff --git a/packages/networks/evm-chains/src/models/TokenTransaction.ts b/packages/networks/evm-chains/src/models/TokenTransaction.ts index 0fc193f..86b21b6 100644 --- a/packages/networks/evm-chains/src/models/TokenTransaction.ts +++ b/packages/networks/evm-chains/src/models/TokenTransaction.ts @@ -3,16 +3,24 @@ import ERC20 from '../../resources/erc20.json' import { hexToNumber } from '@multiplechain/utils' import { TransactionStatusEnum } from '@multiplechain/types' import { ContractTransaction } from './ContractTransaction.ts' -import type { TransactionDescription, TransactionResponse } from 'ethers' +import type { TransactionDescription, TransactionResponse, InterfaceAbi } from 'ethers' import { AssetDirectionEnum, type TokenTransactionInterface } from '@multiplechain/types' export class TokenTransaction extends ContractTransaction implements TokenTransactionInterface { + /** + * @param {string} hash + * @param {InterfaceAbi} ABI + */ + constructor(hash: string, ABI?: InterfaceAbi) { + super(hash, ABI ?? ERC20) + } + /** * @param {TransactionResponse} response * @returns {Promise} */ async decodeData(response?: TransactionResponse): Promise { - return await super.decodeDataBase(ERC20, response) + return await super.decodeData(response) } /** From 275b8f6970f62f7afd24ee3d9cbce7a118e42eaa Mon Sep 17 00:00:00 2001 From: Halil Beycan <50718965+BeycanDeveloper@users.noreply.github.com> Date: Sun, 31 Mar 2024 18:18:28 +0800 Subject: [PATCH 073/114] removed unused --- packages/networks/evm-chains/tests/models.spec.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/networks/evm-chains/tests/models.spec.ts b/packages/networks/evm-chains/tests/models.spec.ts index 64fb12c..6291ee7 100644 --- a/packages/networks/evm-chains/tests/models.spec.ts +++ b/packages/networks/evm-chains/tests/models.spec.ts @@ -1,6 +1,5 @@ import { describe, it, expect } from 'vitest' -import ERC20 from '../resources/erc20.json' import { Transaction } from '../src/models/Transaction.ts' import { AssetDirectionEnum, TransactionStatusEnum } from '@multiplechain/types' import { ContractTransaction } from '../src/models/ContractTransaction.ts' @@ -77,7 +76,7 @@ describe('Contract Transaction', () => { }) it('Decode Data', async () => { - const result = await tx.decodeData(ERC20) + const result = await tx.decodeData() expect(result?.args[0]).toBe('0xbBa4d06D1cEf94b35aDeCfDa893523907fdD36DE') }) }) From 3d0431f1061697c59d6e7208902bf411247ab36f Mon Sep 17 00:00:00 2001 From: Halil Beycan <50718965+BeycanDeveloper@users.noreply.github.com> Date: Sun, 31 Mar 2024 19:10:00 +0800 Subject: [PATCH 074/114] all listeners done --- .../src/services/TransactionListener.ts | 87 ++++++++++++++++++- .../networks/evm-chains/tests/assets.spec.ts | 2 +- .../networks/evm-chains/tests/models.spec.ts | 20 +---- 3 files changed, 86 insertions(+), 23 deletions(-) diff --git a/packages/networks/evm-chains/src/services/TransactionListener.ts b/packages/networks/evm-chains/src/services/TransactionListener.ts index 349e631..27abeda 100644 --- a/packages/networks/evm-chains/src/services/TransactionListener.ts +++ b/packages/networks/evm-chains/src/services/TransactionListener.ts @@ -16,6 +16,7 @@ import { TransactionListenerProcessIndex } from '@multiplechain/types' import { ContractTransaction } from '../models/ContractTransaction.ts' import type { WebSocketProvider, JsonRpcApiProvider, EventFilter, Log } from 'ethers' import { TokenTransaction } from '../models/TokenTransaction.ts' +import { NftTransaction } from '../models/NftTransaction.ts' export class TransactionListener implements TransactionListenerInterface @@ -65,6 +66,11 @@ export class TransactionListener */ dynamicStop: () => void = () => {} + /** + * Triggered transactions + */ + triggeredTransactions: string[] = [] + /** * @param type - Transaction type * @param filter - Transaction listener filter @@ -126,9 +132,12 @@ export class TransactionListener * @param transaction - Transaction data */ trigger(transaction: DynamicTransactionType): void { - this.callbacks.forEach((callback) => { - callback(transaction) - }) + if (!this.triggeredTransactions.includes(transaction.id)) { + this.triggeredTransactions.push(transaction.id) + this.callbacks.forEach((callback) => { + callback(transaction) + }) + } } /** @@ -353,6 +362,76 @@ export class TransactionListener * NFT transaction process */ nftProcess(): void { - // NFT transaction process + const filter = this.filter as DynamicTransactionListenerFilterType + + const params: EventFilter = { + topics: [id('Transfer(address,address,uint256)')] + } + + if (filter.address !== undefined) { + params.address = filter.address + } + + const callback = async (transactionLog: Log): Promise => { + const transaction = new NftTransaction(transactionLog.transactionHash) + const data = await transaction.getData() + + if (data === null) { + return + } + + const decodedData = await transaction.decodeData(data.response) + + if (decodedData === null) { + return + } + + if (decodedData.name !== 'transferFrom') { + return + } + + interface ParamsType { + signer?: string + sender?: string + receiver?: string + } + + const expectedParams: ParamsType = {} + const receivedParams: ParamsType = {} + + if (filter.signer !== undefined) { + expectedParams.signer = filter.signer.toLowerCase() + receivedParams.signer = data.response.from.toLowerCase() + } + + if (filter.sender !== undefined) { + expectedParams.sender = filter.sender.toLowerCase() + receivedParams.sender = decodedData.args[0].toLowerCase() + } + + if (filter.receiver !== undefined) { + expectedParams.receiver = filter.receiver.toLowerCase() + receivedParams.receiver = decodedData.args[1].toLowerCase() + } + + if (!objectsEqual(expectedParams, receivedParams)) { + return + } + + if (filter.nftId !== undefined) { + await transaction.wait() + const nftId = await transaction.getNftId() + if (nftId !== filter.nftId) { + return + } + } + + this.trigger(transaction) + } + + void this.webSocket.on(params, callback) + this.dynamicStop = () => { + void this.webSocket.off(params, callback) + } } } diff --git a/packages/networks/evm-chains/tests/assets.spec.ts b/packages/networks/evm-chains/tests/assets.spec.ts index f8a450f..a7b2381 100644 --- a/packages/networks/evm-chains/tests/assets.spec.ts +++ b/packages/networks/evm-chains/tests/assets.spec.ts @@ -13,7 +13,7 @@ import { TransactionSigner } from '../src/services/TransactionSigner.ts' const coinTransferTestIsActive = false const tokenTransferTestIsActive = false const tokenApproveTestIsActive = false -const tokenTransferFromTestIsActive = false +const tokenTransferFromTestIsActive = true const nftTransactionTestIsActive = false const balanceTestAddress = '0x760A4d3D03928D1e8541A7644B34370c1b79aa9F' diff --git a/packages/networks/evm-chains/tests/models.spec.ts b/packages/networks/evm-chains/tests/models.spec.ts index 6291ee7..4b21dea 100644 --- a/packages/networks/evm-chains/tests/models.spec.ts +++ b/packages/networks/evm-chains/tests/models.spec.ts @@ -1,11 +1,10 @@ import { describe, it, expect } from 'vitest' import { Transaction } from '../src/models/Transaction.ts' -import { AssetDirectionEnum, TransactionStatusEnum } from '@multiplechain/types' -import { ContractTransaction } from '../src/models/ContractTransaction.ts' +import { NftTransaction } from '../src/models/NftTransaction.ts' import { CoinTransaction } from '../src/models/CoinTransaction.ts' import { TokenTransaction } from '../src/models/TokenTransaction.ts' -import { NftTransaction } from '../src/models/NftTransaction.ts' +import { AssetDirectionEnum, TransactionStatusEnum } from '@multiplechain/types' const etherTransferTx = '0x566002399664e92f82ed654c181095bdd7ff3d3f1921d963257585891f622251' const tokenTransferTx = '0xdabda3905e585db91768f2ef877f7fbef7c0e8612c0a09c7b379981bdbc48975' @@ -66,21 +65,6 @@ describe('Transaction', () => { }) }) -describe('Contract Transaction', () => { - const tx = new ContractTransaction(tokenTransferTx) - - it('Address', async () => { - expect((await tx.getAddress()).toLowerCase()).toBe( - '0x4294cb0dD25dC9140B5127f247cBd47Eeb673431'.toLowerCase() - ) - }) - - it('Decode Data', async () => { - const result = await tx.decodeData() - expect(result?.args[0]).toBe('0xbBa4d06D1cEf94b35aDeCfDa893523907fdD36DE') - }) -}) - describe('Coin Transaction', () => { const tx = new CoinTransaction(etherTransferTx) From 849ec3536e3be617029df692d0f4831b8f35ba4e Mon Sep 17 00:00:00 2001 From: Halil Beycan <50718965+BeycanDeveloper@users.noreply.github.com> Date: Sun, 31 Mar 2024 20:42:08 +0800 Subject: [PATCH 075/114] improved --- .../evm-chains/src/models/Transaction.ts | 1 + .../src/services/TransactionListener.ts | 89 ++++++------------- 2 files changed, 29 insertions(+), 61 deletions(-) diff --git a/packages/networks/evm-chains/src/models/Transaction.ts b/packages/networks/evm-chains/src/models/Transaction.ts index be2a3aa..03c0c1a 100644 --- a/packages/networks/evm-chains/src/models/Transaction.ts +++ b/packages/networks/evm-chains/src/models/Transaction.ts @@ -47,6 +47,7 @@ export class Transaction implements TransactionInterface { if (this.data?.response !== undefined && this.data?.receipt !== null) { return this.data } + console.log('getData', this.id) try { const response = await this.ethers.getTransaction(this.id) if (response === null) { diff --git a/packages/networks/evm-chains/src/services/TransactionListener.ts b/packages/networks/evm-chains/src/services/TransactionListener.ts index 27abeda..d0072f3 100644 --- a/packages/networks/evm-chains/src/services/TransactionListener.ts +++ b/packages/networks/evm-chains/src/services/TransactionListener.ts @@ -6,17 +6,17 @@ import type { DynamicTransactionListenerFilterType } from '@multiplechain/types' -import { id } from 'ethers' import { Provider } from './Provider.ts' import type { Ethers } from './Ethers.ts' +import { id, zeroPadValue } from 'ethers' import { objectsEqual } from '@multiplechain/utils' import { Transaction } from '../models/Transaction.ts' +import { NftTransaction } from '../models/NftTransaction.ts' import { CoinTransaction } from '../models/CoinTransaction.ts' +import { TokenTransaction } from '../models/TokenTransaction.ts' import { TransactionListenerProcessIndex } from '@multiplechain/types' import { ContractTransaction } from '../models/ContractTransaction.ts' import type { WebSocketProvider, JsonRpcApiProvider, EventFilter, Log } from 'ethers' -import { TokenTransaction } from '../models/TokenTransaction.ts' -import { NftTransaction } from '../models/NftTransaction.ts' export class TransactionListener implements TransactionListenerInterface @@ -213,17 +213,17 @@ export class TransactionListener coinProcess(): void { const filter = this.filter as DynamicTransactionListenerFilterType - const callback = async (transactionId: string): Promise => { - if ( - filter.signer !== undefined && - filter.sender !== undefined && - filter.signer !== filter.sender - ) { - throw new Error( - 'Sender and signer must be the same in coin transactions. Or only one of them can be defined.' - ) - } + if ( + filter.signer !== undefined && + filter.sender !== undefined && + filter.signer !== filter.sender + ) { + throw new Error( + 'Sender and signer must be the same in coin transactions. Or only one of them can be defined.' + ) + } + const callback = async (transactionId: string): Promise => { const tx = await this.ethers.getTransaction(transactionId) const contractBytecode = await this.ethers.getByteCode(tx?.to ?? '') @@ -282,11 +282,12 @@ export class TransactionListener .filter as DynamicTransactionListenerFilterType const params: EventFilter = { - topics: [id('Transfer(address,address,uint256)')] - } - - if (filter.address !== undefined) { - params.address = filter.address + address: filter.address, + topics: [ + id('Transfer(address,address,uint256)'), + filter.sender !== undefined ? zeroPadValue(filter.sender, 32) : null, + filter.receiver !== undefined ? zeroPadValue(filter.receiver, 32) : null + ] } const callback = async (transactionLog: Log): Promise => { @@ -309,8 +310,6 @@ export class TransactionListener interface ParamsType { signer?: string - sender?: string - receiver?: string } const expectedParams: ParamsType = {} @@ -321,22 +320,6 @@ export class TransactionListener receivedParams.signer = data.response.from.toLowerCase() } - if (filter.sender !== undefined) { - expectedParams.sender = filter.sender.toLowerCase() - receivedParams.sender = - decodedData.name === 'transfer' - ? data.response.from.toLowerCase() - : decodedData.args[0].toLowerCase() - } - - if (filter.receiver !== undefined) { - expectedParams.receiver = filter.receiver.toLowerCase() - receivedParams.receiver = - decodedData.name === 'transfer' - ? decodedData.args[0].toLowerCase() - : decodedData.args[1].toLowerCase() - } - if (!objectsEqual(expectedParams, receivedParams)) { return } @@ -365,11 +348,15 @@ export class TransactionListener const filter = this.filter as DynamicTransactionListenerFilterType const params: EventFilter = { - topics: [id('Transfer(address,address,uint256)')] - } - - if (filter.address !== undefined) { - params.address = filter.address + address: filter.address, + topics: [ + id('Transfer(address,address,uint256)'), + filter.sender !== undefined ? zeroPadValue(filter.sender, 32) : null, + filter.receiver !== undefined ? zeroPadValue(filter.receiver, 32) : null, + filter.nftId !== undefined + ? zeroPadValue(`0x0${filter.nftId.toString(16)}`, 32) + : null + ] } const callback = async (transactionLog: Log): Promise => { @@ -392,8 +379,6 @@ export class TransactionListener interface ParamsType { signer?: string - sender?: string - receiver?: string } const expectedParams: ParamsType = {} @@ -404,28 +389,10 @@ export class TransactionListener receivedParams.signer = data.response.from.toLowerCase() } - if (filter.sender !== undefined) { - expectedParams.sender = filter.sender.toLowerCase() - receivedParams.sender = decodedData.args[0].toLowerCase() - } - - if (filter.receiver !== undefined) { - expectedParams.receiver = filter.receiver.toLowerCase() - receivedParams.receiver = decodedData.args[1].toLowerCase() - } - if (!objectsEqual(expectedParams, receivedParams)) { return } - if (filter.nftId !== undefined) { - await transaction.wait() - const nftId = await transaction.getNftId() - if (nftId !== filter.nftId) { - return - } - } - this.trigger(transaction) } From a3f0bb62b80802bf59a8418ef21d78529827db33 Mon Sep 17 00:00:00 2001 From: Halil Beycan <50718965+BeycanDeveloper@users.noreply.github.com> Date: Sun, 31 Mar 2024 20:42:21 +0800 Subject: [PATCH 076/114] removed --- packages/networks/evm-chains/src/models/Transaction.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/networks/evm-chains/src/models/Transaction.ts b/packages/networks/evm-chains/src/models/Transaction.ts index 03c0c1a..be2a3aa 100644 --- a/packages/networks/evm-chains/src/models/Transaction.ts +++ b/packages/networks/evm-chains/src/models/Transaction.ts @@ -47,7 +47,6 @@ export class Transaction implements TransactionInterface { if (this.data?.response !== undefined && this.data?.receipt !== null) { return this.data } - console.log('getData', this.id) try { const response = await this.ethers.getTransaction(this.id) if (response === null) { From 955266ab4f68231978d50d1dd70dfeea7a376865 Mon Sep 17 00:00:00 2001 From: Halil Beycan <50718965+BeycanDeveloper@users.noreply.github.com> Date: Sun, 31 Mar 2024 21:23:31 +0800 Subject: [PATCH 077/114] added provider to constructors for optional --- .../networks/evm-chains/src/assets/Coin.ts | 32 ++++++++++----- .../evm-chains/src/assets/Contract.ts | 27 ++++++++---- .../networks/evm-chains/src/assets/NFT.ts | 27 ++++++------ .../networks/evm-chains/src/assets/Token.ts | 41 ++++++++----------- .../evm-chains/src/models/CoinTransaction.ts | 3 +- .../src/models/ContractTransaction.ts | 8 ++-- .../evm-chains/src/models/NftTransaction.ts | 6 ++- .../evm-chains/src/models/TokenTransaction.ts | 6 ++- .../evm-chains/src/models/Transaction.ts | 6 +-- .../evm-chains/src/services/Ethers.ts | 13 +++--- .../src/services/TransactionSigner.ts | 18 +++++--- 11 files changed, 106 insertions(+), 81 deletions(-) diff --git a/packages/networks/evm-chains/src/assets/Coin.ts b/packages/networks/evm-chains/src/assets/Coin.ts index 8d9f630..8f0b039 100644 --- a/packages/networks/evm-chains/src/assets/Coin.ts +++ b/packages/networks/evm-chains/src/assets/Coin.ts @@ -5,13 +5,24 @@ import type { TransactionData } from '../services/TransactionSigner.ts' import { ErrorTypeEnum, type CoinInterface } from '@multiplechain/types' export class Coin implements CoinInterface { + /** + * Blockchain network provider + */ + provider: Provider + + /** + * @param {Provider} provider network provider + */ + constructor(provider?: Provider) { + this.provider = provider ?? Provider.instance + } + /** * @returns Coin name */ getName(): string { return ( - Provider.instance.network.nativeCurrency.name ?? - Provider.instance.network.nativeCurrency.symbol + this.provider.network.nativeCurrency.name ?? this.provider.network.nativeCurrency.symbol ) } @@ -19,14 +30,14 @@ export class Coin implements CoinInterface { * @returns Coin symbol */ getSymbol(): string { - return Provider.instance.network.nativeCurrency.symbol + return this.provider.network.nativeCurrency.symbol } /** * @returns Decimal value of the coin */ getDecimals(): number { - return Provider.instance.network.nativeCurrency.decimals + return this.provider.network.nativeCurrency.decimals } /** @@ -34,7 +45,7 @@ export class Coin implements CoinInterface { * @returns Wallet balance as currency of TOKEN or COIN assets */ async getBalance(owner: string): Promise { - const balance = await Provider.instance.ethers.getBalance(owner) + const balance = await this.provider.ethers.getBalance(owner) return hexToNumber(balance.toString(), this.getDecimals()) } @@ -52,21 +63,20 @@ export class Coin implements CoinInterface { throw new Error(ErrorTypeEnum.INSUFFICIENT_BALANCE) } - const { network, ethers } = Provider.instance const hexAmount = numberToHex(amount, this.getDecimals()) const txData: TransactionData = { data: '0x', to: receiver, from: sender, - chainId: network.id, - value: hexAmount + value: hexAmount, + chainId: this.provider.network.id } const [gasPrice, nonce, gasLimit] = await Promise.all([ - ethers.getGasPrice(), - ethers.getNonce(sender), - ethers.getEstimateGas(txData) + this.provider.ethers.getGasPrice(), + this.provider.ethers.getNonce(sender), + this.provider.ethers.getEstimateGas(txData) ]) txData.nonce = nonce diff --git a/packages/networks/evm-chains/src/assets/Contract.ts b/packages/networks/evm-chains/src/assets/Contract.ts index e7fbefd..7ef3b56 100644 --- a/packages/networks/evm-chains/src/assets/Contract.ts +++ b/packages/networks/evm-chains/src/assets/Contract.ts @@ -1,6 +1,7 @@ -import type { ContractInterface } from '@multiplechain/types' -import type { Contract as EthersContract } from 'ethers' import { Provider } from '../services/Provider.ts' +import type { Ethers } from '../services/Ethers.ts' +import type { ContractInterface } from '@multiplechain/types' +import type { Contract as EthersContract, InterfaceAbi } from 'ethers' export class Contract implements ContractInterface { /** @@ -11,22 +12,34 @@ export class Contract implements ContractInterface { /** * Contract ABI */ - ABI: object[] + ABI: InterfaceAbi /** * Ethers contract */ ethersContract: EthersContract + /** + * Blockchain network provider + */ + provider: Provider + + /** + * Ethers service + */ + ethers: Ethers + /** * @param address Contract address * @param ABIArray Contract ABI + * @param provider Blockchain network provider */ - constructor(address: string, ABI: object[]) { - this.ABI = ABI + constructor(address: string, provider?: Provider, ABI?: InterfaceAbi) { + this.ABI = ABI ?? [] this.address = address - const { ethers } = Provider.instance - this.ethersContract = ethers.contract(address, ABI, ethers.jsonRpc) + this.provider = provider ?? Provider.instance + this.ethers = this.provider.ethers + this.ethersContract = this.ethers.contract(address, this.ABI, this.ethers.jsonRpc) } /** diff --git a/packages/networks/evm-chains/src/assets/NFT.ts b/packages/networks/evm-chains/src/assets/NFT.ts index 5dea597..e2973ef 100644 --- a/packages/networks/evm-chains/src/assets/NFT.ts +++ b/packages/networks/evm-chains/src/assets/NFT.ts @@ -1,12 +1,13 @@ import { Contract } from './Contract.ts' +import type { InterfaceAbi } from 'ethers' import ERC721 from '../../resources/erc721.json' -import { Provider } from '../services/Provider.ts' +import type { Provider } from '../services/Provider.ts' import { TransactionSigner } from '../services/TransactionSigner.ts' import { ErrorTypeEnum, type NftInterface } from '@multiplechain/types' export class NFT extends Contract implements NftInterface { - constructor(address: string) { - super(address, ERC721) + constructor(address: string, provider?: Provider, ABI?: InterfaceAbi) { + super(address, provider, ABI ?? ERC721) } /** @@ -92,11 +93,9 @@ export class NFT extends Contract implements NftInterface { } } - const { network, ethers } = Provider.instance - const [gasPrice, nonce, data, gasLimit] = await Promise.all([ - ethers.getGasPrice(), - ethers.getNonce(spender), + this.provider.ethers.getGasPrice(), + this.provider.ethers.getNonce(spender), this.getMethodData('transferFrom', owner, receiver, nftId), this.getMethodEstimateGas('transferFrom', spender, owner, receiver, nftId) ]) @@ -108,8 +107,8 @@ export class NFT extends Contract implements NftInterface { gasLimit, value: '0x0', from: spender, - chainId: network.id, - to: this.getAddress() + to: this.getAddress(), + chainId: this.provider.network.id }) } @@ -133,11 +132,9 @@ export class NFT extends Contract implements NftInterface { throw new Error(ErrorTypeEnum.UNAUTHORIZED_ADDRESS) } - const { network, ethers } = Provider.instance - const [gasPrice, nonce, data, gasLimit] = await Promise.all([ - ethers.getGasPrice(), - ethers.getNonce(owner), + this.provider.ethers.getGasPrice(), + this.provider.ethers.getNonce(owner), this.getMethodData('approve', spender, nftId), this.getMethodEstimateGas('approve', owner, spender, nftId) ]) @@ -149,8 +146,8 @@ export class NFT extends Contract implements NftInterface { gasLimit, value: '0x0', from: owner, - chainId: network.id, - to: this.getAddress() + to: this.getAddress(), + chainId: this.provider.network.id }) } } diff --git a/packages/networks/evm-chains/src/assets/Token.ts b/packages/networks/evm-chains/src/assets/Token.ts index 25bcd80..d8717ae 100644 --- a/packages/networks/evm-chains/src/assets/Token.ts +++ b/packages/networks/evm-chains/src/assets/Token.ts @@ -1,14 +1,14 @@ -import { hexToNumber, numberToHex } from '@multiplechain/utils' -import { ErrorTypeEnum, type TokenInterface } from '@multiplechain/types' - import { Contract } from './Contract.ts' +import type { InterfaceAbi } from 'ethers' import ERC20 from '../../resources/erc20.json' -import { Provider } from '../services/Provider.ts' +import type { Provider } from '../services/Provider.ts' +import { hexToNumber, numberToHex } from '@multiplechain/utils' import { TransactionSigner } from '../services/TransactionSigner.ts' +import { ErrorTypeEnum, type TokenInterface } from '@multiplechain/types' export class Token extends Contract implements TokenInterface { - constructor(address: string) { - super(address, ERC20) + constructor(address: string, provider?: Provider, ABI?: InterfaceAbi) { + super(address, provider, ABI ?? ERC20) } /** @@ -85,12 +85,10 @@ export class Token extends Contract implements TokenInterface { throw new Error(ErrorTypeEnum.INSUFFICIENT_BALANCE) } - const { network, ethers } = Provider.instance - const hexAmount = numberToHex(amount, await this.getDecimals()) const [gasPrice, nonce, data, gasLimit] = await Promise.all([ - ethers.getGasPrice(), - ethers.getNonce(sender), + this.provider.ethers.getGasPrice(), + this.provider.ethers.getNonce(sender), this.getMethodData('transfer', receiver, hexAmount), this.getMethodEstimateGas('transfer', sender, receiver, hexAmount) ]) @@ -102,8 +100,8 @@ export class Token extends Contract implements TokenInterface { gasLimit, value: '0x0', from: sender, - chainId: network.id, - to: this.getAddress() + to: this.getAddress(), + chainId: this.provider.network.id }) } @@ -140,13 +138,11 @@ export class Token extends Contract implements TokenInterface { throw new Error(ErrorTypeEnum.INVALID_AMOUNT) } - const { network, ethers } = Provider.instance - const hexAmount = numberToHex(amount, await this.getDecimals()) const [gasPrice, nonce, data, gasLimit] = await Promise.all([ - ethers.getGasPrice(), - ethers.getNonce(spender), + this.provider.ethers.getGasPrice(), + this.provider.ethers.getNonce(spender), this.getMethodData('transferFrom', owner, receiver, hexAmount), this.getMethodEstimateGas('transferFrom', spender, owner, receiver, hexAmount) ]) @@ -158,8 +154,8 @@ export class Token extends Contract implements TokenInterface { gasLimit, value: '0x0', from: spender, - chainId: network.id, - to: this.getAddress() + to: this.getAddress(), + chainId: this.provider.network.id }) } @@ -180,12 +176,11 @@ export class Token extends Contract implements TokenInterface { throw new Error(ErrorTypeEnum.INSUFFICIENT_BALANCE) } - const { network, ethers } = Provider.instance const hexAmount = numberToHex(amount, await this.getDecimals()) const [gasPrice, nonce, data, gasLimit] = await Promise.all([ - ethers.getGasPrice(), - ethers.getNonce(owner), + this.provider.ethers.getGasPrice(), + this.provider.ethers.getNonce(owner), this.getMethodData('approve', spender, hexAmount), this.getMethodEstimateGas('approve', owner, spender, hexAmount) ]) @@ -197,8 +192,8 @@ export class Token extends Contract implements TokenInterface { gasLimit, value: '0x0', from: owner, - chainId: network.id, - to: this.getAddress() + to: this.getAddress(), + chainId: this.provider.network.id }) } } diff --git a/packages/networks/evm-chains/src/models/CoinTransaction.ts b/packages/networks/evm-chains/src/models/CoinTransaction.ts index 6c0202a..b84a798 100644 --- a/packages/networks/evm-chains/src/models/CoinTransaction.ts +++ b/packages/networks/evm-chains/src/models/CoinTransaction.ts @@ -1,6 +1,5 @@ import { Transaction } from './Transaction.ts' import { hexToNumber } from '@multiplechain/utils' -import { Provider } from '../services/Provider.ts' import { TransactionStatusEnum } from '@multiplechain/types' import { AssetDirectionEnum, type CoinTransactionInterface } from '@multiplechain/types' @@ -25,7 +24,7 @@ export class CoinTransaction extends Transaction implements CoinTransactionInter */ async getAmount(): Promise { const data = await this.getData() - const { decimals } = Provider.instance.network.nativeCurrency + const { decimals } = this.provider.network.nativeCurrency return hexToNumber((data?.response.value ?? 0).toString(), decimals) } diff --git a/packages/networks/evm-chains/src/models/ContractTransaction.ts b/packages/networks/evm-chains/src/models/ContractTransaction.ts index 60d6b00..a1792ec 100644 --- a/packages/networks/evm-chains/src/models/ContractTransaction.ts +++ b/packages/networks/evm-chains/src/models/ContractTransaction.ts @@ -6,6 +6,7 @@ import { type TransactionResponse, type TransactionDescription } from 'ethers' +import type { Provider } from '../services/Provider.ts' export class ContractTransaction extends Transaction implements ContractTransactionInterface { /** @@ -15,11 +16,12 @@ export class ContractTransaction extends Transaction implements ContractTransact /** * @param {string} hash + * @param {Provider} provider * @param {InterfaceAbi} ABI */ - constructor(hash: string, ABI: InterfaceAbi = []) { - super(hash) - this.ABI = ABI + constructor(hash: string, provider?: Provider, ABI?: InterfaceAbi) { + super(hash, provider) + this.ABI = ABI ?? [] } /** diff --git a/packages/networks/evm-chains/src/models/NftTransaction.ts b/packages/networks/evm-chains/src/models/NftTransaction.ts index 9e010c8..43dfe4f 100644 --- a/packages/networks/evm-chains/src/models/NftTransaction.ts +++ b/packages/networks/evm-chains/src/models/NftTransaction.ts @@ -1,4 +1,5 @@ import ERC721 from '../../resources/erc721.json' +import type { Provider } from '../services/Provider.ts' import { ContractTransaction } from './ContractTransaction.ts' import type { NftTransactionInterface } from '@multiplechain/types' import { TransactionStatusEnum, AssetDirectionEnum } from '@multiplechain/types' @@ -7,10 +8,11 @@ import type { TransactionDescription, TransactionResponse, InterfaceAbi } from ' export class NftTransaction extends ContractTransaction implements NftTransactionInterface { /** * @param {string} hash + * @param {Provider} provider * @param {InterfaceAbi} ABI */ - constructor(hash: string, ABI?: InterfaceAbi) { - super(hash, ABI ?? ERC721) + constructor(hash: string, provider?: Provider, ABI?: InterfaceAbi) { + super(hash, provider, ABI ?? ERC721) } /** diff --git a/packages/networks/evm-chains/src/models/TokenTransaction.ts b/packages/networks/evm-chains/src/models/TokenTransaction.ts index 86b21b6..252dfe9 100644 --- a/packages/networks/evm-chains/src/models/TokenTransaction.ts +++ b/packages/networks/evm-chains/src/models/TokenTransaction.ts @@ -1,6 +1,7 @@ import { Token } from '../assets/Token.ts' import ERC20 from '../../resources/erc20.json' import { hexToNumber } from '@multiplechain/utils' +import type { Provider } from '../services/Provider.ts' import { TransactionStatusEnum } from '@multiplechain/types' import { ContractTransaction } from './ContractTransaction.ts' import type { TransactionDescription, TransactionResponse, InterfaceAbi } from 'ethers' @@ -9,10 +10,11 @@ import { AssetDirectionEnum, type TokenTransactionInterface } from '@multiplecha export class TokenTransaction extends ContractTransaction implements TokenTransactionInterface { /** * @param {string} hash + * @param {Provider} provider * @param {InterfaceAbi} ABI */ - constructor(hash: string, ABI?: InterfaceAbi) { - super(hash, ABI ?? ERC20) + constructor(hash: string, provider?: Provider, ABI?: InterfaceAbi) { + super(hash, provider, ABI ?? ERC20) } /** diff --git a/packages/networks/evm-chains/src/models/Transaction.ts b/packages/networks/evm-chains/src/models/Transaction.ts index be2a3aa..c1c015d 100644 --- a/packages/networks/evm-chains/src/models/Transaction.ts +++ b/packages/networks/evm-chains/src/models/Transaction.ts @@ -34,10 +34,10 @@ export class Transaction implements TransactionInterface { /** * @param id Transaction ID */ - constructor(id: string) { + constructor(id: string, provider?: Provider) { this.id = id - this.provider = Provider.instance - this.ethers = Provider.instance.ethers + this.provider = provider ?? Provider.instance + this.ethers = this.provider.ethers } /** diff --git a/packages/networks/evm-chains/src/services/Ethers.ts b/packages/networks/evm-chains/src/services/Ethers.ts index fdd299f..951d6a7 100644 --- a/packages/networks/evm-chains/src/services/Ethers.ts +++ b/packages/networks/evm-chains/src/services/Ethers.ts @@ -2,16 +2,15 @@ import type { Block, BlockTag, EthersError, + InterfaceAbi, JsonRpcSigner, TransactionReceipt, TransactionResponse } from 'ethers' - -import { Wallet, Contract, ContractFactory, JsonRpcProvider, WebSocketProvider } from 'ethers' - import { sleep } from '@multiplechain/utils' import type { EvmNetworkConfigInterface } from './Provider.ts' import type { TransactionData } from '../services/TransactionSigner.ts' +import { Wallet, Contract, ContractFactory, JsonRpcProvider, WebSocketProvider } from 'ethers' export type { EthersError } from 'ethers' @@ -43,13 +42,13 @@ export class Ethers { /** * @param {String} address - * @param {object[]} abi + * @param {InterfaceAbi} abi * @param {JsonRpcSigner} signer * @returns {Promise} */ public contract( address: string, - abi: object[], + abi: InterfaceAbi, signer?: JsonRpcSigner | JsonRpcProvider ): Contract { return new Contract(address, abi, signer) @@ -65,13 +64,13 @@ export class Ethers { } /** - * @param {object[]} abi + * @param {InterfaceAbi} abi * @param {String} bytecode * @param {JsonRpcSigner} signer * @returns {Promise} */ public contractFactory( - abi: object[], + abi: InterfaceAbi, bytecode: string, signer?: JsonRpcSigner | JsonRpcProvider ): ContractFactory { diff --git a/packages/networks/evm-chains/src/services/TransactionSigner.ts b/packages/networks/evm-chains/src/services/TransactionSigner.ts index d90d055..f1b21d9 100644 --- a/packages/networks/evm-chains/src/services/TransactionSigner.ts +++ b/packages/networks/evm-chains/src/services/TransactionSigner.ts @@ -18,8 +18,6 @@ export interface TransactionData extends TransactionRequest { gas?: BigNumberish } -const { ethers } = Provider.instance - export class TransactionSigner implements TransactionSignerInterface { /** * Transaction data from the blockchain network @@ -42,11 +40,19 @@ export class TransactionSigner implements TransactionSignerInterface { wallet: Wallet /** - * @param rawData - Transaction data + * Blockchain network provider + */ + provider: Provider + + /** + * @param rawData Transaction data + * @param type Transaction type + * @param provider Blockchain network provider */ - constructor(rawData: TransactionData, type?: TransactionTypeEnum) { + constructor(rawData: TransactionData, type?: TransactionTypeEnum, provider?: Provider) { this.type = type this.rawData = rawData + this.provider = provider ?? Provider.instance } /** @@ -55,7 +61,7 @@ export class TransactionSigner implements TransactionSignerInterface { */ public async sign(privateKey: string): Promise { try { - this.wallet = ethers.wallet(privateKey) + this.wallet = this.provider.ethers.wallet(privateKey) this.signedData = await this.wallet.signTransaction(this.rawData) return this } catch (error) { @@ -73,7 +79,7 @@ export class TransactionSigner implements TransactionSignerInterface { * @returns Promise of the transaction */ async send(): Promise { - const txId = (await ethers.jsonRpc.send('eth_sendRawTransaction', [ + const txId = (await this.provider.ethers.jsonRpc.send('eth_sendRawTransaction', [ this.signedData ])) as string switch (this.type) { From 2fcc0a20a9ab57776608195a70a0d2a0ae2346ad Mon Sep 17 00:00:00 2001 From: Halil Beycan <50718965+BeycanDeveloper@users.noreply.github.com> Date: Sun, 31 Mar 2024 21:52:52 +0800 Subject: [PATCH 078/114] updated comments --- .../networks/evm-chains/src/assets/Coin.ts | 17 +++---- .../evm-chains/src/assets/Contract.ts | 28 +++++------ .../networks/evm-chains/src/assets/NFT.ts | 47 ++++++++++++------- .../networks/evm-chains/src/assets/Token.ts | 47 +++++++++++-------- .../evm-chains/src/models/CoinTransaction.ts | 13 ++--- .../src/models/ContractTransaction.ts | 16 +++---- .../evm-chains/src/models/NftTransaction.ts | 33 +++++-------- .../evm-chains/src/models/TokenTransaction.ts | 35 +++++--------- .../evm-chains/src/models/Transaction.ts | 23 +++++---- .../src/services/TransactionListener.ts | 2 +- .../src/services/TransactionSigner.ts | 2 +- .../networks/evm-chains/tests/assets.spec.ts | 20 ++------ packages/networks/evm-chains/tests/setup.ts | 6 +-- 13 files changed, 140 insertions(+), 149 deletions(-) diff --git a/packages/networks/evm-chains/src/assets/Coin.ts b/packages/networks/evm-chains/src/assets/Coin.ts index 8f0b039..eca9c0c 100644 --- a/packages/networks/evm-chains/src/assets/Coin.ts +++ b/packages/networks/evm-chains/src/assets/Coin.ts @@ -18,7 +18,7 @@ export class Coin implements CoinInterface { } /** - * @returns Coin name + * @returns {string} Coin name */ getName(): string { return ( @@ -27,22 +27,22 @@ export class Coin implements CoinInterface { } /** - * @returns Coin symbol + * @returns {string} Coin symbol */ getSymbol(): string { return this.provider.network.nativeCurrency.symbol } /** - * @returns Decimal value of the coin + * @returns {number} Decimal value of the coin */ getDecimals(): number { return this.provider.network.nativeCurrency.decimals } /** - * @param owner Wallet address - * @returns Wallet balance as currency of TOKEN or COIN assets + * @param {string} owner Wallet address + * @returns {Promise} Wallet balance as currency of COIN */ async getBalance(owner: string): Promise { const balance = await this.provider.ethers.getBalance(owner) @@ -50,9 +50,10 @@ export class Coin implements CoinInterface { } /** - * @param sender Sender wallet address - * @param receiver Receiver wallet address - * @param amount Amount of assets that will be transferred + * @param {string} sender Sender wallet address + * @param {string} receiver Receiver wallet address + * @param {number} amount Amount of assets that will be transferred + * @returns {Promise} Transaction signer */ async transfer(sender: string, receiver: string, amount: number): Promise { if (amount < 0) { diff --git a/packages/networks/evm-chains/src/assets/Contract.ts b/packages/networks/evm-chains/src/assets/Contract.ts index 7ef3b56..2b7de08 100644 --- a/packages/networks/evm-chains/src/assets/Contract.ts +++ b/packages/networks/evm-chains/src/assets/Contract.ts @@ -30,9 +30,9 @@ export class Contract implements ContractInterface { ethers: Ethers /** - * @param address Contract address - * @param ABIArray Contract ABI - * @param provider Blockchain network provider + * @param {string} address Contract address + * @param {Provider} provider Blockchain network provider + * @param {InterfaceAbi} ABI Contract ABI */ constructor(address: string, provider?: Provider, ABI?: InterfaceAbi) { this.ABI = ABI ?? [] @@ -43,35 +43,35 @@ export class Contract implements ContractInterface { } /** - * @returns Contract address + * @returns {string} Contract address */ getAddress(): string { return this.address } /** - * @param method Method name - * @param args Method parameters - * @returns Method result + * @param {string} method Method name + * @param {any[]} args Method parameters + * @returns {Promise} Method result */ async callMethod(method: string, ...args: any[]): Promise { return this.ethersContract[method](...args) // eslint-disable-line } /** - * @param method Method name - * @param args Method parameters - * @returns Method data + * @param {string} method Method name + * @param {any[]} args Sender wallet address + * @returns {Promise} Encoded method data */ async getMethodData(method: string, ...args: any[]): Promise { return this.ethersContract.interface.encodeFunctionData(method, args) } /** - * @param method Method name - * @param from Sender wallet address - * @param args Method parameters - * @returns Gas estimate + * @param {string} method Method name + * @param {string} from Sender wallet address + * @param {any[]} args Method parameters + * @returns {Promise} Gas limit */ async getMethodEstimateGas(method: string, from: string, ...args: any[]): Promise { return Number(await this.ethersContract[method].estimateGas(...args, { from })) // eslint-disable-line diff --git a/packages/networks/evm-chains/src/assets/NFT.ts b/packages/networks/evm-chains/src/assets/NFT.ts index e2973ef..4918609 100644 --- a/packages/networks/evm-chains/src/assets/NFT.ts +++ b/packages/networks/evm-chains/src/assets/NFT.ts @@ -6,66 +6,78 @@ import { TransactionSigner } from '../services/TransactionSigner.ts' import { ErrorTypeEnum, type NftInterface } from '@multiplechain/types' export class NFT extends Contract implements NftInterface { + /** + * @param {string} address Contract address + * @param {Provider} provider Blockchain network provider + * @param {InterfaceAbi} ABI Contract ABI + */ constructor(address: string, provider?: Provider, ABI?: InterfaceAbi) { super(address, provider, ABI ?? ERC721) } /** - * @returns Contract name + * @returns {Promise} NFT name */ async getName(): Promise { return await this.callMethod('name') } /** - * @returns Contract symbol + * @returns {Promise} NFT symbol */ async getSymbol(): Promise { return await this.callMethod('symbol') } /** - * @param owner Wallet address - * @returns Number of tokens of owner + * @param {string} owner Wallet address + * @returns {Promise} Wallet balance as currency of NFT */ async getBalance(owner: string): Promise { return Number(await this.callMethod('balanceOf', owner)) } /** - * @param nftId NFT ID - * @returns NFT owner wallet address + * @param {number} nftId NFT ID + * @returns {Promise} Wallet address of the owner of the NFT */ async getOwner(nftId: number): Promise { return await this.callMethod('ownerOf', nftId) } /** - * @param nftId NFT ID - * @returns NFT URI + * @param {number} nftId NFT ID + * @returns {Promise} URI of the NFT */ async getTokenURI(nftId: number): Promise { return await this.callMethod('tokenURI', nftId) } /** - * @param nftId ID of the NFT that will be transferred - * @returns Amount of the tokens that is being used by spender + * @param {number} nftId ID of the NFT that will be transferred + * @returns {Promise} Wallet address of the approved spender */ async getApproved(nftId: number): Promise { return await this.callMethod('getApproved', nftId) } /** - * @param sender Sender address - * @param receiver Receiver address - * @param nftId NFT ID - * @returns Transaction signer + * @param {string} sender Sender address + * @param {string} receiver Receiver address + * @param {number} nftId NFT ID + * @returns {Promise} Transaction signer */ async transfer(sender: string, receiver: string, nftId: number): Promise { return await this.transferFrom(sender, sender, receiver, nftId) } + /** + * @param {string} spender Spender address + * @param {string} owner Owner address + * @param {string} receiver Receiver address + * @param {number} nftId NFT ID + * @returns {Promise} Transaction signer + */ async transferFrom( spender: string, owner: string, @@ -114,9 +126,10 @@ export class NFT extends Contract implements NftInterface { /** * Gives permission to the spender to spend owner's tokens - * @param owner Address of owner of the tokens that will be used - * @param spender Address of the spender that will use the tokens of owner - * @param nftId ID of the NFT that will be transferred + * @param {string} owner Address of owner of the tokens that will be used + * @param {string} spender Address of the spender that will use the tokens of owner + * @param {number} nftId ID of the NFT that will be transferred + * @returns {Promise} Transaction signer */ async approve(owner: string, spender: string, nftId: number): Promise { // Check if tokens exist diff --git a/packages/networks/evm-chains/src/assets/Token.ts b/packages/networks/evm-chains/src/assets/Token.ts index d8717ae..96c160f 100644 --- a/packages/networks/evm-chains/src/assets/Token.ts +++ b/packages/networks/evm-chains/src/assets/Token.ts @@ -7,34 +7,39 @@ import { TransactionSigner } from '../services/TransactionSigner.ts' import { ErrorTypeEnum, type TokenInterface } from '@multiplechain/types' export class Token extends Contract implements TokenInterface { + /** + * @param {string} address Contract address + * @param {Provider} provider Blockchain network provider + * @param {InterfaceAbi} ABI Contract ABI + */ constructor(address: string, provider?: Provider, ABI?: InterfaceAbi) { super(address, provider, ABI ?? ERC20) } /** - * @returns Token name + * @returns {Promise} Token name */ async getName(): Promise { return await this.callMethod('name') } /** - * @returns Token symbol + * @returns {Promise} Token symbol */ async getSymbol(): Promise { return await this.callMethod('symbol') } /** - * @returns Decimal value of the coin + * @returns {Promise} Decimal value of the token */ async getDecimals(): Promise { return Number(await this.callMethod('decimals')) } /** - * @param owner Wallet address - * @returns Wallet balance as currency of TOKEN or COIN assets + * @param {string} owner Wallet address + * @returns {Promise} Wallet balance as currency of TOKEN */ async getBalance(owner: string): Promise { const [decimals, balance] = await Promise.all([ @@ -45,7 +50,7 @@ export class Token extends Contract implements TokenInterface { } /** - * @returns Total supply of the token + * @returns {Promise} Total supply of the token */ async getTotalSupply(): Promise { const [decimals, totalSupply] = await Promise.all([ @@ -56,9 +61,9 @@ export class Token extends Contract implements TokenInterface { } /** - * @param owner Address of owner of the tokens that is being used - * @param spender Address of the spender that is using the tokens of owner - * @returns Amount of the tokens that is being used by spender + * @param {string} owner Address of owner of the tokens that is being used + * @param {string} spender Address of the spender that is using the tokens of owner + * @returns {Promise} Amount of tokens that the spender is allowed to spend */ async getAllowance(owner: string, spender: string): Promise { const [decimals, allowance] = await Promise.all([ @@ -70,9 +75,10 @@ export class Token extends Contract implements TokenInterface { /** * transfer() method is the main method for processing transfers for fungible assets (TOKEN, COIN) - * @param sender Sender wallet address - * @param receiver Receiver wallet address - * @param amount Amount of assets that will be transferred + * @param {string} sender Sender wallet address + * @param {string} receiver Receiver wallet address + * @param {number} amount Amount of assets that will be transferred + * @returns {Promise} Transaction signer */ async transfer(sender: string, receiver: string, amount: number): Promise { if (amount <= 0) { @@ -106,11 +112,11 @@ export class Token extends Contract implements TokenInterface { } /** - * @param spender Address of the spender of transaction - * @param owner Sender wallet address - * @param receiver Receiver wallet address - * @param amount Amount of tokens that will be transferred - * @returns {Promise} + * @param {string} spender Address of the spender of transaction + * @param {string} owner Sender wallet address + * @param {string} receiver Receiver wallet address + * @param {number} amount Amount of tokens that will be transferred + * @returns {Promise} Transaction signer */ async transferFrom( spender: string, @@ -161,9 +167,10 @@ export class Token extends Contract implements TokenInterface { /** * Gives permission to the spender to spend owner's tokens - * @param owner Address of owner of the tokens that will be used - * @param spender Address of the spender that will use the tokens of owner - * @param amount Amount of the tokens that will be used + * @param {string} owner Address of owner of the tokens that will be used + * @param {string} spender Address of the spender that will use the tokens of owner + * @param {number} amount Amount of the tokens that will be used + * @returns {Promise} Transaction signer */ async approve(owner: string, spender: string, amount: number): Promise { if (amount < 0) { diff --git a/packages/networks/evm-chains/src/models/CoinTransaction.ts b/packages/networks/evm-chains/src/models/CoinTransaction.ts index b84a798..c1c5bca 100644 --- a/packages/networks/evm-chains/src/models/CoinTransaction.ts +++ b/packages/networks/evm-chains/src/models/CoinTransaction.ts @@ -5,7 +5,7 @@ import { AssetDirectionEnum, type CoinTransactionInterface } from '@multiplechai export class CoinTransaction extends Transaction implements CoinTransactionInterface { /** - * @returns Wallet address of the sender of transaction + * @returns {Promise} Wallet address of the receiver of transaction */ async getReceiver(): Promise { const data = await this.getData() @@ -13,14 +13,14 @@ export class CoinTransaction extends Transaction implements CoinTransactionInter } /** - * @returns Wallet address of the sender of transaction + * @returns {Promise} Wallet address of the sender of transaction */ async getSender(): Promise { return await this.getSigner() } /** - * @returns Transfer amount of the transaction (coin) + * @returns {Promise} Amount of coin that will be transferred */ async getAmount(): Promise { const data = await this.getData() @@ -29,9 +29,10 @@ export class CoinTransaction extends Transaction implements CoinTransactionInter } /** - * @param direction - Direction of the transaction (asset) - * @param address - Wallet address of the receiver or sender of the transaction, dependant on direction - * @param amount Amount of assets that will be transferred + * @param {AssetDirectionEnum} direction - Direction of the transaction (asset) + * @param {string} address - Wallet address of the receiver or sender of the transaction, dependant on direction + * @param {number} amount Amount of assets that will be transferred + * @returns {Promise} Status of the transaction */ async verifyTransfer( direction: AssetDirectionEnum, diff --git a/packages/networks/evm-chains/src/models/ContractTransaction.ts b/packages/networks/evm-chains/src/models/ContractTransaction.ts index a1792ec..6878378 100644 --- a/packages/networks/evm-chains/src/models/ContractTransaction.ts +++ b/packages/networks/evm-chains/src/models/ContractTransaction.ts @@ -15,17 +15,17 @@ export class ContractTransaction extends Transaction implements ContractTransact ABI: InterfaceAbi /** - * @param {string} hash - * @param {Provider} provider - * @param {InterfaceAbi} ABI + * @param {string} id Transaction id + * @param {Provider} provider Blockchain network provider + * @param {InterfaceAbi} ABI Contract ABI */ - constructor(hash: string, provider?: Provider, ABI?: InterfaceAbi) { - super(hash, provider) + constructor(id: string, provider?: Provider, ABI?: InterfaceAbi) { + super(id, provider) this.ABI = ABI ?? [] } /** - * @returns {Promise} + * @returns {Promise} Contract address of the transaction */ async getAddress(): Promise { const data = await this.getData() @@ -33,8 +33,8 @@ export class ContractTransaction extends Transaction implements ContractTransact } /** - * @param {TransactionResponse} response - * @returns {Promise} + * @param {TransactionResponse} response Transaction response + * @returns {Promise} Decoded transaction data */ async decodeData(response?: TransactionResponse): Promise { if (response === undefined) { diff --git a/packages/networks/evm-chains/src/models/NftTransaction.ts b/packages/networks/evm-chains/src/models/NftTransaction.ts index 43dfe4f..08fcec2 100644 --- a/packages/networks/evm-chains/src/models/NftTransaction.ts +++ b/packages/networks/evm-chains/src/models/NftTransaction.ts @@ -1,30 +1,22 @@ +import type { InterfaceAbi } from 'ethers' import ERC721 from '../../resources/erc721.json' import type { Provider } from '../services/Provider.ts' import { ContractTransaction } from './ContractTransaction.ts' import type { NftTransactionInterface } from '@multiplechain/types' import { TransactionStatusEnum, AssetDirectionEnum } from '@multiplechain/types' -import type { TransactionDescription, TransactionResponse, InterfaceAbi } from 'ethers' export class NftTransaction extends ContractTransaction implements NftTransactionInterface { /** - * @param {string} hash - * @param {Provider} provider - * @param {InterfaceAbi} ABI + * @param {string} id Transaction id + * @param {Provider} provider Blockchain network provider + * @param {InterfaceAbi} ABI Contract ABI */ - constructor(hash: string, provider?: Provider, ABI?: InterfaceAbi) { - super(hash, provider, ABI ?? ERC721) + constructor(id: string, provider?: Provider, ABI?: InterfaceAbi) { + super(id, provider, ABI ?? ERC721) } /** - * @param {TransactionResponse} response - * @returns {Promise} - */ - async decodeData(response?: TransactionResponse): Promise { - return await super.decodeData(response) - } - - /** - * @returns Wallet address of the sender of transaction + * @returns {Promise} Receiver wallet address */ async getReceiver(): Promise { const decoded = await this.decodeData() @@ -41,7 +33,7 @@ export class NftTransaction extends ContractTransaction implements NftTransactio } /** - * @returns Wallet address of the sender of transaction + * @returns {Promise} Sender wallet address */ async getSender(): Promise { const decoded = await this.decodeData() @@ -58,17 +50,18 @@ export class NftTransaction extends ContractTransaction implements NftTransactio } /** - * @returns ID of the NFT + * @returns {Promise} NFT ID */ async getNftId(): Promise { return Number((await this.decodeData())?.args[2] ?? 0) } /** - * @param direction - Direction of the transaction (nft) - * @param address - Wallet address of the receiver or sender of the transaction, dependant on direction - * @param nftId ID of the NFT that will be transferred + * @param {AssetDirectionEnum} direction - Direction of the transaction (nft) + * @param {string} address - Wallet address of the receiver or sender of the transaction, dependant on direction + * @param {number} nftId ID of the NFT that will be transferred * @override verifyTransfer() in AssetTransactionInterface + * @returns {Promise} Status of the transaction */ async verifyTransfer( direction: AssetDirectionEnum, diff --git a/packages/networks/evm-chains/src/models/TokenTransaction.ts b/packages/networks/evm-chains/src/models/TokenTransaction.ts index 252dfe9..b270328 100644 --- a/packages/networks/evm-chains/src/models/TokenTransaction.ts +++ b/packages/networks/evm-chains/src/models/TokenTransaction.ts @@ -1,32 +1,24 @@ import { Token } from '../assets/Token.ts' +import type { InterfaceAbi } from 'ethers' import ERC20 from '../../resources/erc20.json' import { hexToNumber } from '@multiplechain/utils' import type { Provider } from '../services/Provider.ts' import { TransactionStatusEnum } from '@multiplechain/types' import { ContractTransaction } from './ContractTransaction.ts' -import type { TransactionDescription, TransactionResponse, InterfaceAbi } from 'ethers' import { AssetDirectionEnum, type TokenTransactionInterface } from '@multiplechain/types' export class TokenTransaction extends ContractTransaction implements TokenTransactionInterface { /** - * @param {string} hash - * @param {Provider} provider - * @param {InterfaceAbi} ABI + * @param {string} id Transaction id + * @param {Provider} provider Blockchain network provider + * @param {InterfaceAbi} ABI Contract ABI */ - constructor(hash: string, provider?: Provider, ABI?: InterfaceAbi) { - super(hash, provider, ABI ?? ERC20) + constructor(id: string, provider?: Provider, ABI?: InterfaceAbi) { + super(id, provider, ABI ?? ERC20) } /** - * @param {TransactionResponse} response - * @returns {Promise} - */ - async decodeData(response?: TransactionResponse): Promise { - return await super.decodeData(response) - } - - /** - * @returns Wallet address of the sender of transaction + * @return {Promise} Receiver wallet address */ async getReceiver(): Promise { const decoded = await this.decodeData() @@ -60,11 +52,7 @@ export class TokenTransaction extends ContractTransaction implements TokenTransa } /** - * @returns Wallet address of the sender of transaction - */ - - /** - * @returns Transfer amount of the transaction (token) + * @returns {Promise} Amount of tokens that will be transferred */ async getAmount(): Promise { const token = new Token(await this.getAddress()) @@ -81,9 +69,10 @@ export class TokenTransaction extends ContractTransaction implements TokenTransa } /** - * @param direction - Direction of the transaction (token) - * @param address - Wallet address of the owner or spender of the transaction, dependant on direction - * @param amount Amount of tokens that will be approved + * @param {AssetDirectionEnum} direction - Direction of the transaction (token) + * @param {string} address - Wallet address of the owner or spender of the transaction, dependant on direction + * @param {number} amount Amount of tokens that will be approved + * @returns {Promise} Status of the transaction */ async verifyTransfer( direction: AssetDirectionEnum, diff --git a/packages/networks/evm-chains/src/models/Transaction.ts b/packages/networks/evm-chains/src/models/Transaction.ts index c1c015d..cd3cfd2 100644 --- a/packages/networks/evm-chains/src/models/Transaction.ts +++ b/packages/networks/evm-chains/src/models/Transaction.ts @@ -41,7 +41,7 @@ export class Transaction implements TransactionInterface { } /** - * @returns Raw transaction data that is taken by blockchain network via RPC. + * @returns {Promise} Transaction data */ async getData(): Promise { if (this.data?.response !== undefined && this.data?.receipt !== null) { @@ -62,6 +62,10 @@ export class Transaction implements TransactionInterface { } } + /** + * @param {number} ms - Milliseconds to wait for the transaction to be confirmed. Default is 4000ms + * @returns {Promise} Status of the transaction + */ async wait(ms: number = 4000): Promise { return await new Promise((resolve, reject) => { const check = async (): Promise => { @@ -84,15 +88,14 @@ export class Transaction implements TransactionInterface { } /** - * @returns Transaction id from the blockchain network - * this can be different names like txid, hash, signature etc. + * @returns {string} Transaction id from the blockchain network */ getId(): string { return this.id } /** - * @returns Blockchain explorer URL of the transaction. Dependant on network. + * @returns {string} URL of the transaction on the blockchain explorer */ getUrl(): string { let explorerUrl = this.provider.network.explorerUrl @@ -102,7 +105,7 @@ export class Transaction implements TransactionInterface { } /** - * @returns Wallet address of the sender of transaction + * @returns {Promise} Signer wallet address of the transaction */ async getSigner(): Promise { const data = await this.getData() @@ -110,7 +113,7 @@ export class Transaction implements TransactionInterface { } /** - * @returns Transaction fee as native coin amount + * @returns {Promise} Fee of the transaction */ async getFee(): Promise { const data = await this.getData() @@ -124,7 +127,7 @@ export class Transaction implements TransactionInterface { } /** - * @returns Block ID of the transaction + * @returns {Promise} Block number that transaction */ async getBlockNumber(): Promise { const data = await this.getData() @@ -132,7 +135,7 @@ export class Transaction implements TransactionInterface { } /** - * @returns UNIX timestamp of the date that block is added to blockchain + * @returns {Promise} Timestamp of the block that transaction */ async getBlockTimestamp(): Promise { const blockNumber = await this.getBlockNumber() @@ -141,7 +144,7 @@ export class Transaction implements TransactionInterface { } /** - * @returns Confirmation count of the block that transaction is included + * @returns {Promise} Confirmation count of the block that transaction */ async getBlockConfirmationCount(): Promise { const blockNumber = await this.getBlockNumber() @@ -151,7 +154,7 @@ export class Transaction implements TransactionInterface { } /** - * @returns Status of the transaction + * @returns {Promise} Status of the transaction */ async getStatus(): Promise { const data = await this.getData() diff --git a/packages/networks/evm-chains/src/services/TransactionListener.ts b/packages/networks/evm-chains/src/services/TransactionListener.ts index d0072f3..41ff371 100644 --- a/packages/networks/evm-chains/src/services/TransactionListener.ts +++ b/packages/networks/evm-chains/src/services/TransactionListener.ts @@ -75,7 +75,7 @@ export class TransactionListener * @param type - Transaction type * @param filter - Transaction listener filter */ - constructor(type: T, filter?: DynamicTransactionListenerFilterType, provider?: Provider) { + constructor(type: T, provider?: Provider, filter?: DynamicTransactionListenerFilterType) { this.type = type this.filter = filter this.provider = provider ?? Provider.instance diff --git a/packages/networks/evm-chains/src/services/TransactionSigner.ts b/packages/networks/evm-chains/src/services/TransactionSigner.ts index f1b21d9..8b99cd4 100644 --- a/packages/networks/evm-chains/src/services/TransactionSigner.ts +++ b/packages/networks/evm-chains/src/services/TransactionSigner.ts @@ -49,7 +49,7 @@ export class TransactionSigner implements TransactionSignerInterface { * @param type Transaction type * @param provider Blockchain network provider */ - constructor(rawData: TransactionData, type?: TransactionTypeEnum, provider?: Provider) { + constructor(rawData: TransactionData, provider?: Provider, type?: TransactionTypeEnum) { this.type = type this.rawData = rawData this.provider = provider ?? Provider.instance diff --git a/packages/networks/evm-chains/tests/assets.spec.ts b/packages/networks/evm-chains/tests/assets.spec.ts index a7b2381..d2c38ab 100644 --- a/packages/networks/evm-chains/tests/assets.spec.ts +++ b/packages/networks/evm-chains/tests/assets.spec.ts @@ -1,11 +1,9 @@ import { describe, it, expect, assert } from 'vitest' -import ERC20 from '../resources/erc20.json' import { NFT } from '../src/assets/NFT.ts' import { Coin } from '../src/assets/Coin.ts' import { Token } from '../src/assets/Token.ts' -import { numberToHex, fixFloat } from '@multiplechain/utils' -import { Contract } from '../src/assets/Contract.ts' +import { fixFloat } from '@multiplechain/utils' import { Transaction } from '../src/models/Transaction.ts' import { TransactionStatusEnum } from '@multiplechain/types' import { TransactionSigner } from '../src/services/TransactionSigner.ts' @@ -13,8 +11,8 @@ import { TransactionSigner } from '../src/services/TransactionSigner.ts' const coinTransferTestIsActive = false const tokenTransferTestIsActive = false const tokenApproveTestIsActive = false -const tokenTransferFromTestIsActive = true -const nftTransactionTestIsActive = false +const tokenTransferFromTestIsActive = false +const nftTransactionTestIsActive = true const balanceTestAddress = '0x760A4d3D03928D1e8541A7644B34370c1b79aa9F' const coinBalanceTestAmount = 0.01 @@ -90,18 +88,6 @@ describe('Coin', () => { }) }) -describe('Contract', () => { - it('getMethodData', async () => { - const contract = new Contract(tokenTestAddress, ERC20) - const decimals = await contract.callMethod('decimals') - const hexAmount = numberToHex(tokenBalanceTestAmount, Number(decimals)) - const data = await contract.getMethodData('transfer', receiverTestAddress, hexAmount) - expect(data).toBe( - '0xa9059cbb000000000000000000000000bba4d06d1cef94b35adecfda893523907fdd36de00000000000000000000000000000000000000000000003635c9adc5dea00000' - ) - }) -}) - describe('Token', () => { const token = new Token(tokenTestAddress) diff --git a/packages/networks/evm-chains/tests/setup.ts b/packages/networks/evm-chains/tests/setup.ts index 29541ac..74c5dc0 100644 --- a/packages/networks/evm-chains/tests/setup.ts +++ b/packages/networks/evm-chains/tests/setup.ts @@ -5,10 +5,8 @@ export const provider = new Provider({ hexId: '0xaa36a7', mainnetId: 1, name: 'Ethereum Sepolia Testnet (QR)', - rpcUrl: 'https://sepolia.infura.io/v3/9aa3d95b3bc440fa88ea12eaa4456161', - wsUrl: 'wss://sepolia.infura.io/ws/v3/9aa3d95b3bc440fa88ea12eaa4456161', - // rpcUrl: 'https://dimensional-icy-tent.ethereum-sepolia.quiknode.pro/e6a31d965b3ab5fc57d5980d187121f1894c0eb4/', - // wsUrl: 'wss://dimensional-icy-tent.ethereum-sepolia.quiknode.pro/e6a31d965b3ab5fc57d5980d187121f1894c0eb4/', + rpcUrl: 'https://dimensional-icy-tent.ethereum-sepolia.quiknode.pro/e6a31d965b3ab5fc57d5980d187121f1894c0eb4/', + wsUrl: 'wss://dimensional-icy-tent.ethereum-sepolia.quiknode.pro/e6a31d965b3ab5fc57d5980d187121f1894c0eb4/', explorerUrl: 'https://sepolia.etherscan.io/', nativeCurrency: { symbol: 'ETH', From 6836a2c1fe051aeb4d303cfdf53907aa8ceee157 Mon Sep 17 00:00:00 2001 From: Halil Beycan <50718965+BeycanDeveloper@users.noreply.github.com> Date: Sun, 31 Mar 2024 22:14:13 +0800 Subject: [PATCH 079/114] updated comments --- .../networks/boilerplate/src/assets/Coin.ts | 30 ++++++++---- .../boilerplate/src/assets/Contract.ts | 29 ++++++++---- .../networks/boilerplate/src/assets/NFT.ts | 47 ++++++++++--------- .../networks/boilerplate/src/assets/Token.ts | 42 +++++++++-------- .../boilerplate/src/models/CoinTransaction.ts | 13 ++--- .../src/models/ContractTransaction.ts | 3 ++ .../boilerplate/src/models/NftTransaction.ts | 13 ++--- .../src/models/TokenTransaction.ts | 13 ++--- .../boilerplate/src/models/Transaction.ts | 35 +++++++++----- .../boilerplate/src/services/Provider.ts | 34 +++++++++++++- .../src/services/TransactionListener.ts | 33 +++++++++---- .../evm-chains/src/models/Transaction.ts | 3 +- .../evm-chains/src/services/Ethers.ts | 19 +++++++- .../evm-chains/src/services/Provider.ts | 12 +++-- .../src/services/TransactionListener.ts | 20 ++++++-- .../src/services/TransactionSigner.ts | 15 +++--- 16 files changed, 243 insertions(+), 118 deletions(-) diff --git a/packages/networks/boilerplate/src/assets/Coin.ts b/packages/networks/boilerplate/src/assets/Coin.ts index 1cb667e..778ebd8 100644 --- a/packages/networks/boilerplate/src/assets/Coin.ts +++ b/packages/networks/boilerplate/src/assets/Coin.ts @@ -1,40 +1,54 @@ +import { Provider } from '../services/Provider.ts' import { TransactionSigner } from '../services/TransactionSigner.ts' import type { CoinInterface, TransactionSignerInterface } from '@multiplechain/types' export class Coin implements CoinInterface { /** - * @returns Coin name + * Blockchain network provider + */ + provider: Provider + + /** + * @param {Provider} provider network provider + */ + constructor(provider?: Provider) { + this.provider = provider ?? Provider.instance + } + + /** + * @returns {string} Coin name */ getName(): string { return 'example' } /** - * @returns Coin symbol + * @returns {string} Coin symbol */ getSymbol(): string { return 'example' } /** - * @returns Decimal value of the coin + * @returns {number} Decimal value of the coin */ getDecimals(): number { return 18 } /** - * @param owner Wallet address - * @returns Wallet balance as currency of TOKEN or COIN assets + * @param {string} owner Wallet address + * @returns {Promise} Wallet balance as currency of COIN */ async getBalance(owner: string): Promise { return 0 } /** - * @param sender Sender wallet address - * @param receiver Receiver wallet address - * @param amount Amount of assets that will be transferred + * @param {string} sender Sender wallet address + * @param {string} receiver Receiver wallet address + * @param {number} amount Amount of assets that will be transferred + * @returns {Promise} Transaction signer */ async transfer( sender: string, diff --git a/packages/networks/boilerplate/src/assets/Contract.ts b/packages/networks/boilerplate/src/assets/Contract.ts index e52c40c..d8c2edd 100644 --- a/packages/networks/boilerplate/src/assets/Contract.ts +++ b/packages/networks/boilerplate/src/assets/Contract.ts @@ -1,35 +1,46 @@ +import { Provider } from '../services/Provider.ts' import type { ContractInterface } from '@multiplechain/types' export class Contract implements ContractInterface { + /** + * Contract address + */ address: string /** - * @param address Contract address + * Blockchain network provider + */ + provider: Provider + + /** + * @param {string} address Contract address + * @param {Provider} provider Blockchain network provider */ - constructor(address: string) { + constructor(address: string, provider?: Provider) { this.address = address + this.provider = provider ?? Provider.instance } /** - * @returns Contract address + * @returns {string} Contract address */ getAddress(): string { return this.address } /** - * @param method Method name - * @param args Method parameters - * @returns Method result + * @param {string} method Method name + * @param {any[]} args Method parameters + * @returns {Promise} Method result */ async callMethod(method: string, ...args: any[]): Promise { return {} } /** - * @param method Method name - * @param args Method parameters - * @returns Method data + * @param {string} method Method name + * @param {any[]} args Sender wallet address + * @returns {Promise} Encoded method data */ async getMethodData(method: string, ...args: any[]): Promise { return {} diff --git a/packages/networks/boilerplate/src/assets/NFT.ts b/packages/networks/boilerplate/src/assets/NFT.ts index 7d800cc..f3da454 100644 --- a/packages/networks/boilerplate/src/assets/NFT.ts +++ b/packages/networks/boilerplate/src/assets/NFT.ts @@ -4,56 +4,56 @@ import type { NftInterface, TransactionSignerInterface } from '@multiplechain/ty export class NFT extends Contract implements NftInterface { /** - * @returns Contract name + * @returns {Promise} NFT name */ async getName(): Promise { return 'example' } /** - * @returns Contract symbol + * @returns {Promise} NFT symbol */ async getSymbol(): Promise { return 'example' } /** - * @param owner Wallet address - * @returns Wallet balance as currency of TOKEN or COIN assets + * @param {string} owner Wallet address + * @returns {Promise} Wallet balance as currency of NFT */ async getBalance(owner: string): Promise { return 0 } /** - * @param nftId NFT ID - * @returns NFT owner wallet address + * @param {number} nftId NFT ID + * @returns {Promise} Wallet address of the owner of the NFT */ async getOwner(nftId: number): Promise { return 'example' } /** - * @param nftId NFT ID - * @returns NFT URI + * @param {number} nftId NFT ID + * @returns {Promise} URI of the NFT */ async getTokenURI(nftId: number): Promise { return 'example' } /** - * @param nftId NFT ID - * @returns NFT URI + * @param {number} nftId ID of the NFT that will be transferred + * @returns {Promise} Wallet address of the approved spender */ async getApproved(nftId: number): Promise { return 'example' } /** - * @param sender Sender address - * @param receiver Receiver address - * @param nftId NFT ID - * @returns Transaction signer + * @param {string} sender Sender address + * @param {string} receiver Receiver address + * @param {number} nftId NFT ID + * @returns {Promise} Transaction signer */ async transfer( sender: string, @@ -64,11 +64,11 @@ export class NFT extends Contract implements NftInterface { } /** - * @param spender Spender address - * @param sender Sender address - * @param receiver Receiver address - * @param nftId NFT ID - * @returns Transaction signer + * @param {string} spender Spender address + * @param {string} owner Owner address + * @param {string} receiver Receiver address + * @param {number} nftId NFT ID + * @returns {Promise} Transaction signer */ async transferFrom( spender: string, @@ -80,10 +80,11 @@ export class NFT extends Contract implements NftInterface { } /** - * @param owner Owner of the nft - * @param spender Approved spender - * @param nftId NFT ID - * @returns Transaction signer + * Gives permission to the spender to spend owner's tokens + * @param {string} owner Address of owner of the tokens that will be used + * @param {string} spender Address of the spender that will use the tokens of owner + * @param {number} nftId ID of the NFT that will be transferred + * @returns {Promise} Transaction signer */ async approve( owner: string, diff --git a/packages/networks/boilerplate/src/assets/Token.ts b/packages/networks/boilerplate/src/assets/Token.ts index b59f152..285183a 100644 --- a/packages/networks/boilerplate/src/assets/Token.ts +++ b/packages/networks/boilerplate/src/assets/Token.ts @@ -4,45 +4,45 @@ import type { TokenInterface, TransactionSignerInterface } from '@multiplechain/ export class Token extends Contract implements TokenInterface { /** - * @returns Token name + * @returns {Promise} Token name */ async getName(): Promise { return 'example' } /** - * @returns Token symbol + * @returns {Promise} Token symbol */ async getSymbol(): Promise { return 'example' } /** - * @returns Decimal value of the coin + * @returns {Promise} Decimal value of the token */ async getDecimals(): Promise { return 18 } /** - * @param owner Wallet address - * @returns Wallet balance as currency of TOKEN or COIN assets + * @param {string} owner Wallet address + * @returns {Promise} Wallet balance as currency of TOKEN */ async getBalance(owner: string): Promise { return 0 } /** - * @returns Total supply of the token + * @returns {Promise} Total supply of the token */ async getTotalSupply(): Promise { return 0 } /** - * @param owner Address of owner of the tokens that is being used - * @param spender Address of the spender that is using the tokens of owner - * @returns Amount of the tokens that is being used by spender + * @param {string} owner Address of owner of the tokens that is being used + * @param {string} spender Address of the spender that is using the tokens of owner + * @returns {Promise} Amount of tokens that the spender is allowed to spend */ async getAllowance(owner: string, spender: string): Promise { return 0 @@ -50,9 +50,10 @@ export class Token extends Contract implements TokenInterface { /** * transfer() method is the main method for processing transfers for fungible assets (TOKEN, COIN) - * @param sender Sender wallet address - * @param receiver Receiver wallet address - * @param amount Amount of assets that will be transferred + * @param {string} sender Sender wallet address + * @param {string} receiver Receiver wallet address + * @param {number} amount Amount of assets that will be transferred + * @returns {Promise} Transaction signer */ async transfer( sender: string, @@ -63,11 +64,11 @@ export class Token extends Contract implements TokenInterface { } /** - * @param spender Address of the spender of transaction - * @param owner Sender wallet address - * @param receiver Receiver wallet address - * @param amount Amount of tokens that will be transferred - * @override transfer() in AssetInterface + * @param {string} spender Address of the spender of transaction + * @param {string} owner Sender wallet address + * @param {string} receiver Receiver wallet address + * @param {number} amount Amount of tokens that will be transferred + * @returns {Promise} Transaction signer */ async transferFrom( spender: string, @@ -80,9 +81,10 @@ export class Token extends Contract implements TokenInterface { /** * Gives permission to the spender to spend owner's tokens - * @param owner Address of owner of the tokens that will be used - * @param spender Address of the spender that will use the tokens of owner - * @param amount Amount of the tokens that will be used + * @param {string} owner Address of owner of the tokens that will be used + * @param {string} spender Address of the spender that will use the tokens of owner + * @param {number} amount Amount of the tokens that will be used + * @returns {Promise} Transaction signer */ async approve( owner: string, diff --git a/packages/networks/boilerplate/src/models/CoinTransaction.ts b/packages/networks/boilerplate/src/models/CoinTransaction.ts index 8a02b9a..9857f2e 100644 --- a/packages/networks/boilerplate/src/models/CoinTransaction.ts +++ b/packages/networks/boilerplate/src/models/CoinTransaction.ts @@ -4,30 +4,31 @@ import type { AssetDirectionEnum, CoinTransactionInterface } from '@multiplechai export class CoinTransaction extends Transaction implements CoinTransactionInterface { /** - * @returns Wallet address of the sender of transaction + * @returns {Promise} Wallet address of the receiver of transaction */ async getReceiver(): Promise { return 'example' } /** - * @returns Wallet address of the sender of transaction + * @returns {Promise} Wallet address of the sender of transaction */ async getSender(): Promise { return 'example' } /** - * @returns Transfer amount of the transaction (coin) + * @returns {Promise} Amount of coin that will be transferred */ async getAmount(): Promise { return 0 } /** - * @param direction - Direction of the transaction (asset) - * @param address - Wallet address of the receiver or sender of the transaction, dependant on direction - * @param amount Amount of assets that will be transferred + * @param {AssetDirectionEnum} direction - Direction of the transaction (asset) + * @param {string} address - Wallet address of the receiver or sender of the transaction, dependant on direction + * @param {number} amount Amount of assets that will be transferred + * @returns {Promise} Status of the transaction */ async verifyTransfer( direction: AssetDirectionEnum, diff --git a/packages/networks/boilerplate/src/models/ContractTransaction.ts b/packages/networks/boilerplate/src/models/ContractTransaction.ts index c48396b..ad57241 100644 --- a/packages/networks/boilerplate/src/models/ContractTransaction.ts +++ b/packages/networks/boilerplate/src/models/ContractTransaction.ts @@ -2,6 +2,9 @@ import { Transaction } from './Transaction.ts' import type { ContractTransactionInterface } from '@multiplechain/types' export class ContractTransaction extends Transaction implements ContractTransactionInterface { + /** + * @returns {Promise} Contract address of the transaction + */ async getAddress(): Promise { return 'example' } diff --git a/packages/networks/boilerplate/src/models/NftTransaction.ts b/packages/networks/boilerplate/src/models/NftTransaction.ts index 14500b7..57cf99a 100644 --- a/packages/networks/boilerplate/src/models/NftTransaction.ts +++ b/packages/networks/boilerplate/src/models/NftTransaction.ts @@ -4,31 +4,32 @@ import type { NftTransactionInterface, AssetDirectionEnum } from '@multiplechain export class NftTransaction extends ContractTransaction implements NftTransactionInterface { /** - * @returns Wallet address of the sender of transaction + * @returns {Promise} Receiver wallet address */ async getReceiver(): Promise { return 'example' } /** - * @returns Wallet address of the sender of transaction + * @returns {Promise} Wallet address of the sender of transaction */ async getSender(): Promise { return 'example' } /** - * @returns ID of the NFT + * @returns {Promise} NFT ID */ async getNftId(): Promise { return 0 } /** - * @param direction - Direction of the transaction (nft) - * @param address - Wallet address of the receiver or sender of the transaction, dependant on direction - * @param nftId ID of the NFT that will be transferred + * @param {AssetDirectionEnum} direction - Direction of the transaction (nft) + * @param {string} address - Wallet address of the receiver or sender of the transaction, dependant on direction + * @param {number} nftId ID of the NFT that will be transferred * @override verifyTransfer() in AssetTransactionInterface + * @returns {Promise} Status of the transaction */ async verifyTransfer( direction: AssetDirectionEnum, diff --git a/packages/networks/boilerplate/src/models/TokenTransaction.ts b/packages/networks/boilerplate/src/models/TokenTransaction.ts index 62f3bf0..b1ea29e 100644 --- a/packages/networks/boilerplate/src/models/TokenTransaction.ts +++ b/packages/networks/boilerplate/src/models/TokenTransaction.ts @@ -4,30 +4,31 @@ import type { AssetDirectionEnum, TokenTransactionInterface } from '@multiplecha export class TokenTransaction extends ContractTransaction implements TokenTransactionInterface { /** - * @returns Wallet address of the sender of transaction + * @returns {Promise} Wallet address of the receiver of transaction */ async getReceiver(): Promise { return 'example' } /** - * @returns Wallet address of the sender of transaction + * @returns {Promise} Wallet address of the sender of transaction */ async getSender(): Promise { return 'example' } /** - * @returns Transfer amount of the transaction (token) + * @returns {Promise} Amount of tokens that will be transferred */ async getAmount(): Promise { return 0 } /** - * @param direction - Direction of the transaction (token) - * @param address - Wallet address of the owner or spender of the transaction, dependant on direction - * @param amount Amount of tokens that will be approved + * @param {AssetDirectionEnum} direction - Direction of the transaction (token) + * @param {string} address - Wallet address of the owner or spender of the transaction, dependant on direction + * @param {number} amount Amount of tokens that will be approved + * @returns {Promise} Status of the transaction */ async verifyTransfer( direction: AssetDirectionEnum, diff --git a/packages/networks/boilerplate/src/models/Transaction.ts b/packages/networks/boilerplate/src/models/Transaction.ts index 6c68dde..15f111d 100644 --- a/packages/networks/boilerplate/src/models/Transaction.ts +++ b/packages/networks/boilerplate/src/models/Transaction.ts @@ -1,3 +1,4 @@ +import { Provider } from '../services/Provider.ts' import type { TransactionInterface } from '@multiplechain/types' import { TransactionStatusEnum } from '@multiplechain/types' @@ -7,73 +8,85 @@ export class Transaction implements TransactionInterface { */ id: string - constructor(id: string) { + /** + * Blockchain network provider + */ + provider: Provider + + /** + * @param {string} id Transaction id + * @param {Provider} provider Blockchain network provider + */ + constructor(id: string, provider?: Provider) { this.id = id + this.provider = provider ?? Provider.instance } /** - * @returns Raw transaction data that is taken by blockchain network via RPC. + * @returns {Promise} Transaction data */ async getData(): Promise { return {} } + /** + * @returns {Promise} Wait for the transaction to be confirmed + */ async wait(): Promise { return await Promise.resolve(TransactionStatusEnum.CONFIRMED) } /** - * @returns Transaction id from the blockchain network - * this can be different names like txid, hash, signature etc. + * @returns {string} Transaction ID */ getId(): string { return this.id } /** - * @returns Blockchain explorer URL of the transaction. Dependant on network. + * @returns {string} Transaction URL */ getUrl(): string { return 'example' } /** - * @returns Wallet address of the sender of transaction + * @returns {Promise} Wallet address of the sender of transaction */ async getSigner(): Promise { return 'example' } /** - * @returns Transaction fee as native coin amount + * @returns {Promise} Transaction fee */ async getFee(): Promise { return 0 } /** - * @returns Block ID of the transaction + * @returns {Promise} Block number that transaction */ async getBlockNumber(): Promise { return 0 } /** - * @returns UNIX timestamp of the date that block is added to blockchain + * @returns {Promise} Block timestamp that transaction */ async getBlockTimestamp(): Promise { return 0 } /** - * @returns Confirmation count of the block that transaction is included + * @returns {Promise} Confirmation count of the block */ async getBlockConfirmationCount(): Promise { return 0 } /** - * @returns Status of the transaction + * @returns {Promise} Status of the transaction */ async getStatus(): Promise { return TransactionStatusEnum.CONFIRMED diff --git a/packages/networks/boilerplate/src/services/Provider.ts b/packages/networks/boilerplate/src/services/Provider.ts index 884b47a..9323774 100644 --- a/packages/networks/boilerplate/src/services/Provider.ts +++ b/packages/networks/boilerplate/src/services/Provider.ts @@ -1,4 +1,8 @@ -import type { NetworkConfigInterface, ProviderInterface } from '@multiplechain/types' +import { + ErrorTypeEnum, + type NetworkConfigInterface, + type ProviderInterface +} from '@multiplechain/types' export class Provider implements ProviderInterface { /** @@ -6,6 +10,11 @@ export class Provider implements ProviderInterface { */ network: NetworkConfigInterface + /** + * Static instance of the provider + */ + private static _instance: Provider + /** * @param network - Network configuration of the provider */ @@ -13,6 +22,29 @@ export class Provider implements ProviderInterface { this.network = network } + /** + * Get the static instance of the provider + * @returns {Provider} Provider + */ + static get instance(): Provider { + if (Provider._instance === undefined) { + throw new Error(ErrorTypeEnum.PROVIDER_IS_NOT_INITIALIZED) + } + return Provider._instance + } + + /** + * Initialize the static instance of the provider + * @param {NetworkConfigInterface} network - Network configuration of the provider + * @returns {void} + */ + static initialize(network: NetworkConfigInterface): void { + if (Provider._instance !== undefined) { + throw new Error(ErrorTypeEnum.PROVIDER_IS_ALREADY_INITIALIZED) + } + Provider._instance = new Provider(network) + } + /** * Update network configuration of the provider * @param network - Network configuration of the provider diff --git a/packages/networks/boilerplate/src/services/TransactionListener.ts b/packages/networks/boilerplate/src/services/TransactionListener.ts index 937d12d..e92fff0 100644 --- a/packages/networks/boilerplate/src/services/TransactionListener.ts +++ b/packages/networks/boilerplate/src/services/TransactionListener.ts @@ -6,6 +6,7 @@ import type { DynamicTransactionListenerFilterType } from '@multiplechain/types' +import { Provider } from './Provider.ts' import { TransactionListenerProcessIndex } from '@multiplechain/types' export class TransactionListener @@ -24,26 +25,34 @@ export class TransactionListener /** * Transaction listener filter */ - filter: DynamicTransactionListenerFilterType + filter?: DynamicTransactionListenerFilterType + + /** + * Provider + */ + provider: Provider /** * Listener status */ - status: boolean + status: boolean = false /** - * @param type - Transaction type - * @param filter - Transaction listener filter + * @param {T} type - Transaction type + * @param {Provider} provider - Provider + * @param {DynamicTransactionListenerFilterType} filter - Transaction listener filter */ - constructor(type: T, filter: DynamicTransactionListenerFilterType) { + constructor(type: T, provider?: Provider, filter?: DynamicTransactionListenerFilterType) { this.type = type this.filter = filter + this.provider = provider ?? Provider.instance // @ts-expect-error allow dynamic access this[TransactionListenerProcessIndex[type]]() } /** * Close the listener + * @returns {void} */ stop(): void { // Close the listener @@ -51,6 +60,7 @@ export class TransactionListener /** * Start the listener + * @returns {void} */ start(): void { // Start the listener @@ -58,7 +68,7 @@ export class TransactionListener /** * Get the listener status - * @returns boolean + * @returns {boolean} Listener status */ getStatus(): boolean { return this.status @@ -66,7 +76,8 @@ export class TransactionListener /** * Listen to the transaction events - * @param callback - Callback function + * @param {TransactionListenerCallbackType} callback - Transaction listener callback + * @returns {void} */ on(callback: TransactionListenerCallbackType): void { this.callbacks.push(callback) @@ -74,7 +85,8 @@ export class TransactionListener /** * Trigger the event when a transaction is detected - * @param transaction - Transaction data + * @param {DynamicTransactionType} transaction - Transaction data + * @returns {void} */ trigger(transaction: DynamicTransactionType): void { this.callbacks.forEach((callback) => { @@ -84,6 +96,7 @@ export class TransactionListener /** * General transaction process + * @returns {void} */ generalProcess(): void { // General transaction process @@ -91,6 +104,7 @@ export class TransactionListener /** * Contract transaction process + * @returns {void} */ contractProcess(): void { // Contract transaction process @@ -98,6 +112,7 @@ export class TransactionListener /** * Coin transaction process + * @returns {void} */ coinProcess(): void { // Coin transaction process @@ -105,6 +120,7 @@ export class TransactionListener /** * Token transaction process + * @returns {void} */ tokenProcess(): void { // Token transaction process @@ -112,6 +128,7 @@ export class TransactionListener /** * NFT transaction process + * @returns {void} */ nftProcess(): void { // NFT transaction process diff --git a/packages/networks/evm-chains/src/models/Transaction.ts b/packages/networks/evm-chains/src/models/Transaction.ts index cd3cfd2..10223e9 100644 --- a/packages/networks/evm-chains/src/models/Transaction.ts +++ b/packages/networks/evm-chains/src/models/Transaction.ts @@ -32,7 +32,8 @@ export class Transaction implements TransactionInterface { data: TransactionData /** - * @param id Transaction ID + * @param {string} id Transaction id + * @param {Provider} provider Blockchain network provider */ constructor(id: string, provider?: Provider) { this.id = id diff --git a/packages/networks/evm-chains/src/services/Ethers.ts b/packages/networks/evm-chains/src/services/Ethers.ts index 951d6a7..68f1cce 100644 --- a/packages/networks/evm-chains/src/services/Ethers.ts +++ b/packages/networks/evm-chains/src/services/Ethers.ts @@ -15,10 +15,19 @@ import { Wallet, Contract, ContractFactory, JsonRpcProvider, WebSocketProvider } export type { EthersError } from 'ethers' export class Ethers { + /** + * Network configuration of the provider + */ network: EvmNetworkConfigInterface + /** + * JSON RPC provider + */ jsonRpcProvider: JsonRpcProvider + /** + * WebSocket provider + */ webSocketProvider?: WebSocketProvider /** @@ -32,10 +41,16 @@ export class Ethers { } } + /** + * @returns {JsonRpcProvider} + */ public get jsonRpc(): JsonRpcProvider { return this.jsonRpcProvider } + /** + * @returns {WebSocketProvider | undefined} + */ public get webSocket(): WebSocketProvider | undefined { return this.webSocketProvider } @@ -55,8 +70,8 @@ export class Ethers { } /** - * @param privateKey private key of the wallet - * @param provider provider of the blockchain network + * @param {string} privateKey private key of the wallet + * @param {JsonRpcProvider} provider provider of the blockchain network * @returns {Wallet} */ public wallet(privateKey: string, provider?: JsonRpcProvider): Wallet { diff --git a/packages/networks/evm-chains/src/services/Provider.ts b/packages/networks/evm-chains/src/services/Provider.ts index f4ac7b5..0cf3019 100644 --- a/packages/networks/evm-chains/src/services/Provider.ts +++ b/packages/networks/evm-chains/src/services/Provider.ts @@ -33,7 +33,7 @@ export class Provider implements Omit { /** * Static instance of the provider */ - public static _instance: Provider + private static _instance: Provider /** * @param network - Network configuration of the provider @@ -46,7 +46,7 @@ export class Provider implements Omit { /** * Get the static instance of the provider - * @returns Provider + * @returns {Provider} Provider */ static get instance(): Provider { if (Provider._instance === undefined) { @@ -57,7 +57,8 @@ export class Provider implements Omit { /** * Initialize the static instance of the provider - * @param network - Network configuration of the provider + * @param {EvmNetworkConfigInterface} network - Network configuration of the provider + * @returns {void} */ static initialize(network: EvmNetworkConfigInterface): void { if (Provider._instance !== undefined) { @@ -68,7 +69,8 @@ export class Provider implements Omit { /** * Update network configuration of the provider - * @param network - Network configuration of the provider + * @param {EvmNetworkConfigInterface} network - Network configuration of the provider + * @returns {void} */ update(network: EvmNetworkConfigInterface): void { this.network = network @@ -78,7 +80,7 @@ export class Provider implements Omit { /** * Get the current network configuration is testnet or not - * @returns boolean + * @returns {boolean} */ isTestnet(): boolean { return this.network?.testnet ?? false diff --git a/packages/networks/evm-chains/src/services/TransactionListener.ts b/packages/networks/evm-chains/src/services/TransactionListener.ts index 41ff371..5b3f7d6 100644 --- a/packages/networks/evm-chains/src/services/TransactionListener.ts +++ b/packages/networks/evm-chains/src/services/TransactionListener.ts @@ -72,8 +72,9 @@ export class TransactionListener triggeredTransactions: string[] = [] /** - * @param type - Transaction type - * @param filter - Transaction listener filter + * @param {T} type - Transaction type + * @param {Provider} provider - Provider + * @param {DynamicTransactionListenerFilterType} filter - Transaction listener filter */ constructor(type: T, provider?: Provider, filter?: DynamicTransactionListenerFilterType) { this.type = type @@ -91,6 +92,7 @@ export class TransactionListener /** * Close the listener + * @returns {void} */ stop(): void { if (this.status) { @@ -101,6 +103,7 @@ export class TransactionListener /** * Start the listener + * @returns {void} */ start(): void { if (!this.status) { @@ -112,7 +115,7 @@ export class TransactionListener /** * Get the listener status - * @returns - Listener status + * @returns {boolean} - Listener status */ getStatus(): boolean { return this.status @@ -120,7 +123,8 @@ export class TransactionListener /** * Listen to the transaction events - * @param callback - Callback function + * @param {TransactionListenerCallbackType} callback - Callback function + * @returns {void} */ on(callback: TransactionListenerCallbackType): void { this.start() @@ -129,7 +133,8 @@ export class TransactionListener /** * Trigger the event when a transaction is detected - * @param transaction - Transaction data + * @param {DynamicTransactionType} transaction - Transaction data + * @returns {void} */ trigger(transaction: DynamicTransactionType): void { if (!this.triggeredTransactions.includes(transaction.id)) { @@ -142,6 +147,7 @@ export class TransactionListener /** * General transaction process + * @returns {void} */ generalProcess(): void { const callback = async (transactionId: string): Promise => { @@ -163,6 +169,7 @@ export class TransactionListener /** * Contract transaction process + * @returns {void} */ contractProcess(): void { const filter = this @@ -209,6 +216,7 @@ export class TransactionListener /** * Coin transaction process + * @returns {void} */ coinProcess(): void { const filter = this.filter as DynamicTransactionListenerFilterType @@ -276,6 +284,7 @@ export class TransactionListener /** * Token transaction process + * @returns {void} */ tokenProcess(): void { const filter = this @@ -343,6 +352,7 @@ export class TransactionListener /** * NFT transaction process + * @returns {void} */ nftProcess(): void { const filter = this.filter as DynamicTransactionListenerFilterType diff --git a/packages/networks/evm-chains/src/services/TransactionSigner.ts b/packages/networks/evm-chains/src/services/TransactionSigner.ts index 8b99cd4..c3e3199 100644 --- a/packages/networks/evm-chains/src/services/TransactionSigner.ts +++ b/packages/networks/evm-chains/src/services/TransactionSigner.ts @@ -45,9 +45,9 @@ export class TransactionSigner implements TransactionSignerInterface { provider: Provider /** - * @param rawData Transaction data - * @param type Transaction type - * @param provider Blockchain network provider + * @param {TransactionData} rawData Transaction data + * @param {Provider} provider Blockchain network provider + * @param {TransactionTypeEnum} type Transaction type */ constructor(rawData: TransactionData, provider?: Provider, type?: TransactionTypeEnum) { this.type = type @@ -57,7 +57,8 @@ export class TransactionSigner implements TransactionSignerInterface { /** * Sign the transaction - * @param privateKey - Transaction data + * @param {string} privateKey - Transaction data + * @returns {Promise} Signed transaction data */ public async sign(privateKey: string): Promise { try { @@ -76,7 +77,7 @@ export class TransactionSigner implements TransactionSignerInterface { /** * Send the transaction to the blockchain network - * @returns Promise of the transaction + * @returns {Promise} Transaction data */ async send(): Promise { const txId = (await this.provider.ethers.jsonRpc.send('eth_sendRawTransaction', [ @@ -102,7 +103,7 @@ export class TransactionSigner implements TransactionSignerInterface { /** * Get the raw transaction data - * @returns Transaction data + * @returns {any} Transaction data */ getRawData(): any { return this.rawData @@ -110,7 +111,7 @@ export class TransactionSigner implements TransactionSignerInterface { /** * Get the signed transaction data - * @returns Signed transaction data + * @returns {any} Signed transaction data */ getSignedData(): any { return this.signedData From 333202e93209801e2780c39cf229bb4a522a6c41 Mon Sep 17 00:00:00 2001 From: Halil Beycan <50718965+BeycanDeveloper@users.noreply.github.com> Date: Sun, 31 Mar 2024 22:17:49 +0800 Subject: [PATCH 080/114] updated --- packages/networks/evm-chains/tests/setup.ts | 45 ++++++++++++++------- 1 file changed, 31 insertions(+), 14 deletions(-) diff --git a/packages/networks/evm-chains/tests/setup.ts b/packages/networks/evm-chains/tests/setup.ts index 74c5dc0..8d8014e 100644 --- a/packages/networks/evm-chains/tests/setup.ts +++ b/packages/networks/evm-chains/tests/setup.ts @@ -1,16 +1,33 @@ import { Provider } from '../src/services/Provider.ts' -export const provider = new Provider({ - id: 11155111, - hexId: '0xaa36a7', - mainnetId: 1, - name: 'Ethereum Sepolia Testnet (QR)', - rpcUrl: 'https://dimensional-icy-tent.ethereum-sepolia.quiknode.pro/e6a31d965b3ab5fc57d5980d187121f1894c0eb4/', - wsUrl: 'wss://dimensional-icy-tent.ethereum-sepolia.quiknode.pro/e6a31d965b3ab5fc57d5980d187121f1894c0eb4/', - explorerUrl: 'https://sepolia.etherscan.io/', - nativeCurrency: { - symbol: 'ETH', - name: 'Ethereum', - decimals: 18 - } -}) +const useCustomRpcAndWs = true + +const rpcAndWs = { + rpcUrl: 'https://sepolia.infura.io/v3/9aa3d95b3bc440fa88ea12eaa4456161', + wsUrl: 'wss://sepolia.infura.io/ws/v3/9aa3d95b3bc440fa88ea12eaa4456161' +} + +if (useCustomRpcAndWs) { + rpcAndWs.rpcUrl = + 'https://dimensional-icy-tent.ethereum-sepolia.quiknode.pro/e6a31d965b3ab5fc57d5980d187121f1894c0eb4/' + rpcAndWs.wsUrl = + 'wss://dimensional-icy-tent.ethereum-sepolia.quiknode.pro/e6a31d965b3ab5fc57d5980d187121f1894c0eb4/' +} + +export const provider = new Provider( + Object.assign( + { + id: 11155111, + hexId: '0xaa36a7', + mainnetId: 1, + name: 'Ethereum Sepolia Testnet (QR)', + explorerUrl: 'https://sepolia.etherscan.io/', + nativeCurrency: { + symbol: 'ETH', + name: 'Ethereum', + decimals: 18 + } + }, + rpcAndWs + ) +) From 4eb328dc28084a42019dd794ca3823ca1044e3f8 Mon Sep 17 00:00:00 2001 From: Halil Beycan <50718965+BeycanDeveloper@users.noreply.github.com> Date: Sun, 31 Mar 2024 22:57:24 +0800 Subject: [PATCH 081/114] created different signer classes for assets --- .../networks/evm-chains/src/assets/Coin.ts | 10 ++- .../networks/evm-chains/src/assets/NFT.ts | 12 +-- .../networks/evm-chains/src/assets/Token.ts | 18 +++-- .../src/services/TransactionSigner.ts | 75 ++++++++++--------- 4 files changed, 62 insertions(+), 53 deletions(-) diff --git a/packages/networks/evm-chains/src/assets/Coin.ts b/packages/networks/evm-chains/src/assets/Coin.ts index eca9c0c..878d554 100644 --- a/packages/networks/evm-chains/src/assets/Coin.ts +++ b/packages/networks/evm-chains/src/assets/Coin.ts @@ -1,6 +1,6 @@ import { Provider } from '../services/Provider.ts' import { hexToNumber, numberToHex } from '@multiplechain/utils' -import { TransactionSigner } from '../services/TransactionSigner.ts' +import { CoinTransactionSigner } from '../services/TransactionSigner.ts' import type { TransactionData } from '../services/TransactionSigner.ts' import { ErrorTypeEnum, type CoinInterface } from '@multiplechain/types' @@ -55,7 +55,11 @@ export class Coin implements CoinInterface { * @param {number} amount Amount of assets that will be transferred * @returns {Promise} Transaction signer */ - async transfer(sender: string, receiver: string, amount: number): Promise { + async transfer( + sender: string, + receiver: string, + amount: number + ): Promise { if (amount < 0) { throw new Error(ErrorTypeEnum.INVALID_AMOUNT) } @@ -84,6 +88,6 @@ export class Coin implements CoinInterface { txData.gasPrice = gasPrice txData.gasLimit = gasLimit - return new TransactionSigner(txData) + return new CoinTransactionSigner(txData) } } diff --git a/packages/networks/evm-chains/src/assets/NFT.ts b/packages/networks/evm-chains/src/assets/NFT.ts index 4918609..552af06 100644 --- a/packages/networks/evm-chains/src/assets/NFT.ts +++ b/packages/networks/evm-chains/src/assets/NFT.ts @@ -2,7 +2,7 @@ import { Contract } from './Contract.ts' import type { InterfaceAbi } from 'ethers' import ERC721 from '../../resources/erc721.json' import type { Provider } from '../services/Provider.ts' -import { TransactionSigner } from '../services/TransactionSigner.ts' +import { NftTransactionSigner } from '../services/TransactionSigner.ts' import { ErrorTypeEnum, type NftInterface } from '@multiplechain/types' export class NFT extends Contract implements NftInterface { @@ -67,7 +67,7 @@ export class NFT extends Contract implements NftInterface { * @param {number} nftId NFT ID * @returns {Promise} Transaction signer */ - async transfer(sender: string, receiver: string, nftId: number): Promise { + async transfer(sender: string, receiver: string, nftId: number): Promise { return await this.transferFrom(sender, sender, receiver, nftId) } @@ -83,7 +83,7 @@ export class NFT extends Contract implements NftInterface { owner: string, receiver: string, nftId: number - ): Promise { + ): Promise { // Check if tokens exist const balance = await this.getBalance(owner) @@ -112,7 +112,7 @@ export class NFT extends Contract implements NftInterface { this.getMethodEstimateGas('transferFrom', spender, owner, receiver, nftId) ]) - return new TransactionSigner({ + return new NftTransactionSigner({ data, nonce, gasPrice, @@ -131,7 +131,7 @@ export class NFT extends Contract implements NftInterface { * @param {number} nftId ID of the NFT that will be transferred * @returns {Promise} Transaction signer */ - async approve(owner: string, spender: string, nftId: number): Promise { + async approve(owner: string, spender: string, nftId: number): Promise { // Check if tokens exist const balance = await this.getBalance(owner) @@ -152,7 +152,7 @@ export class NFT extends Contract implements NftInterface { this.getMethodEstimateGas('approve', owner, spender, nftId) ]) - return new TransactionSigner({ + return new NftTransactionSigner({ data, nonce, gasPrice, diff --git a/packages/networks/evm-chains/src/assets/Token.ts b/packages/networks/evm-chains/src/assets/Token.ts index 96c160f..985fbbd 100644 --- a/packages/networks/evm-chains/src/assets/Token.ts +++ b/packages/networks/evm-chains/src/assets/Token.ts @@ -3,7 +3,7 @@ import type { InterfaceAbi } from 'ethers' import ERC20 from '../../resources/erc20.json' import type { Provider } from '../services/Provider.ts' import { hexToNumber, numberToHex } from '@multiplechain/utils' -import { TransactionSigner } from '../services/TransactionSigner.ts' +import { TokenTransactionSigner } from '../services/TransactionSigner.ts' import { ErrorTypeEnum, type TokenInterface } from '@multiplechain/types' export class Token extends Contract implements TokenInterface { @@ -80,7 +80,11 @@ export class Token extends Contract implements TokenInterface { * @param {number} amount Amount of assets that will be transferred * @returns {Promise} Transaction signer */ - async transfer(sender: string, receiver: string, amount: number): Promise { + async transfer( + sender: string, + receiver: string, + amount: number + ): Promise { if (amount <= 0) { throw new Error(ErrorTypeEnum.INVALID_AMOUNT) } @@ -99,7 +103,7 @@ export class Token extends Contract implements TokenInterface { this.getMethodEstimateGas('transfer', sender, receiver, hexAmount) ]) - return new TransactionSigner({ + return new TokenTransactionSigner({ data, nonce, gasPrice, @@ -123,7 +127,7 @@ export class Token extends Contract implements TokenInterface { owner: string, receiver: string, amount: number - ): Promise { + ): Promise { if (amount < 0) { throw new Error(ErrorTypeEnum.INVALID_AMOUNT) } @@ -153,7 +157,7 @@ export class Token extends Contract implements TokenInterface { this.getMethodEstimateGas('transferFrom', spender, owner, receiver, hexAmount) ]) - return new TransactionSigner({ + return new TokenTransactionSigner({ data, nonce, gasPrice, @@ -172,7 +176,7 @@ export class Token extends Contract implements TokenInterface { * @param {number} amount Amount of the tokens that will be used * @returns {Promise} Transaction signer */ - async approve(owner: string, spender: string, amount: number): Promise { + async approve(owner: string, spender: string, amount: number): Promise { if (amount < 0) { throw new Error(ErrorTypeEnum.INVALID_AMOUNT) } @@ -192,7 +196,7 @@ export class Token extends Contract implements TokenInterface { this.getMethodEstimateGas('approve', owner, spender, hexAmount) ]) - return new TransactionSigner({ + return new TokenTransactionSigner({ data, nonce, gasPrice, diff --git a/packages/networks/evm-chains/src/services/TransactionSigner.ts b/packages/networks/evm-chains/src/services/TransactionSigner.ts index c3e3199..2b54da3 100644 --- a/packages/networks/evm-chains/src/services/TransactionSigner.ts +++ b/packages/networks/evm-chains/src/services/TransactionSigner.ts @@ -1,34 +1,21 @@ import type { EthersError } from './Ethers.ts' import { Provider } from '../services/Provider.ts' -import type { TransactionRequest, Wallet, BigNumberish } from 'ethers' -import { - ErrorTypeEnum, - TransactionTypeEnum, - type TransactionSignerInterface -} from '@multiplechain/types' - -// Transactions import { Transaction } from '../models/Transaction.ts' import { NftTransaction } from '../models/NftTransaction.ts' import { CoinTransaction } from '../models/CoinTransaction.ts' import { TokenTransaction } from '../models/TokenTransaction.ts' -import { ContractTransaction } from '../models/ContractTransaction.ts' +import type { TransactionRequest, Wallet, BigNumberish } from 'ethers' +import { ErrorTypeEnum, type TransactionSignerInterface } from '@multiplechain/types' export interface TransactionData extends TransactionRequest { gas?: BigNumberish } - export class TransactionSigner implements TransactionSignerInterface { /** * Transaction data from the blockchain network */ rawData: TransactionData - /** - * Transaction type - */ - type?: TransactionTypeEnum - /** * Signed transaction data */ @@ -47,10 +34,8 @@ export class TransactionSigner implements TransactionSignerInterface { /** * @param {TransactionData} rawData Transaction data * @param {Provider} provider Blockchain network provider - * @param {TransactionTypeEnum} type Transaction type */ - constructor(rawData: TransactionData, provider?: Provider, type?: TransactionTypeEnum) { - this.type = type + constructor(rawData: TransactionData, provider?: Provider) { this.rawData = rawData this.provider = provider ?? Provider.instance } @@ -80,25 +65,11 @@ export class TransactionSigner implements TransactionSignerInterface { * @returns {Promise} Transaction data */ async send(): Promise { - const txId = (await this.provider.ethers.jsonRpc.send('eth_sendRawTransaction', [ - this.signedData - ])) as string - switch (this.type) { - case TransactionTypeEnum.COIN: - return new CoinTransaction(txId) - - case TransactionTypeEnum.TOKEN: - return new TokenTransaction(txId) - - case TransactionTypeEnum.NFT: - return new NftTransaction(txId) - - case TransactionTypeEnum.CONTRACT: - return new ContractTransaction(txId) - - default: - return new Transaction(txId) - } + return new Transaction( + (await this.provider.ethers.jsonRpc.send('eth_sendRawTransaction', [ + this.signedData + ])) as string + ) } /** @@ -117,3 +88,33 @@ export class TransactionSigner implements TransactionSignerInterface { return this.signedData } } + +export class CoinTransactionSigner extends TransactionSigner { + /** + * Send the transaction to the blockchain network + * @returns {Promise} Transaction data + */ + async send(): Promise { + return new CoinTransaction((await super.send()).getId()) + } +} + +export class TokenTransactionSigner extends TransactionSigner { + /** + * Send the transaction to the blockchain network + * @returns {Promise} Transaction data + */ + async send(): Promise { + return new TokenTransaction((await super.send()).getId()) + } +} + +export class NftTransactionSigner extends TransactionSigner { + /** + * Send the transaction to the blockchain network + * @returns {Promise} Transaction data + */ + async send(): Promise { + return new NftTransaction((await super.send()).getId()) + } +} From 41bf26cdc963d832e676233cd3964aa27664ee86 Mon Sep 17 00:00:00 2001 From: Halil Beycan <50718965+BeycanDeveloper@users.noreply.github.com> Date: Sun, 31 Mar 2024 23:00:52 +0800 Subject: [PATCH 082/114] updated --- .../src/services/TransactionSigner.ts | 58 ++++++++++++++++--- 1 file changed, 50 insertions(+), 8 deletions(-) diff --git a/packages/networks/boilerplate/src/services/TransactionSigner.ts b/packages/networks/boilerplate/src/services/TransactionSigner.ts index e492e8c..a76019e 100644 --- a/packages/networks/boilerplate/src/services/TransactionSigner.ts +++ b/packages/networks/boilerplate/src/services/TransactionSigner.ts @@ -1,4 +1,9 @@ -import type { TransactionSignerInterface, TransactionInterface } from '@multiplechain/types' +import { Provider } from '../services/Provider.ts' +import { Transaction } from '../models/Transaction.ts' +import { NftTransaction } from '../models/NftTransaction.ts' +import { CoinTransaction } from '../models/CoinTransaction.ts' +import { TokenTransaction } from '../models/TokenTransaction.ts' +import type { TransactionSignerInterface } from '@multiplechain/types' export class TransactionSigner implements TransactionSignerInterface { /** @@ -12,26 +17,33 @@ export class TransactionSigner implements TransactionSignerInterface { signedData?: any /** - * @param rawData - Transaction data + * Blockchain network provider */ - constructor(rawData: any) { + provider: Provider + + /** + * @param {any} rawData - Transaction data + */ + constructor(rawData: any, provider?: Provider) { this.rawData = rawData + this.provider = provider ?? Provider.instance } /** * Sign the transaction - * @param privateKey - Transaction data + * @param {string} privateKey - Transaction data + * @returns {Promise} Signed transaction data */ - async sign(privateKey: string): Promise { + async sign(privateKey: string): Promise { return await Promise.resolve(this) } /** * Send the transaction to the blockchain network - * @returns Promise of the transaction + * @returns {Promise} */ - async send(): Promise { - return await Promise.resolve(this.signedData) + async send(): Promise { + return await Promise.resolve(new Transaction('example')) } /** @@ -50,3 +62,33 @@ export class TransactionSigner implements TransactionSignerInterface { return this.signedData } } + +export class CoinTransactionSigner extends TransactionSigner { + /** + * Send the transaction to the blockchain network + * @returns {Promise} Transaction data + */ + async send(): Promise { + return new CoinTransaction((await super.send()).getId()) + } +} + +export class TokenTransactionSigner extends TransactionSigner { + /** + * Send the transaction to the blockchain network + * @returns {Promise} Transaction data + */ + async send(): Promise { + return new TokenTransaction((await super.send()).getId()) + } +} + +export class NftTransactionSigner extends TransactionSigner { + /** + * Send the transaction to the blockchain network + * @returns {Promise} Transaction data + */ + async send(): Promise { + return new NftTransaction((await super.send()).getId()) + } +} From e1802e1ab2aae846b47e22f35b2b7354086488a7 Mon Sep 17 00:00:00 2001 From: Halil Beycan <50718965+BeycanDeveloper@users.noreply.github.com> Date: Sun, 31 Mar 2024 23:15:59 +0800 Subject: [PATCH 083/114] updated --- .../src/services/TransactionListener.ts | 29 ++++++++++++++----- 1 file changed, 21 insertions(+), 8 deletions(-) diff --git a/packages/networks/boilerplate/src/services/TransactionListener.ts b/packages/networks/boilerplate/src/services/TransactionListener.ts index e92fff0..fd17438 100644 --- a/packages/networks/boilerplate/src/services/TransactionListener.ts +++ b/packages/networks/boilerplate/src/services/TransactionListener.ts @@ -37,6 +37,11 @@ export class TransactionListener */ status: boolean = false + /** + * Triggered transactions + */ + triggeredTransactions: string[] = [] + /** * @param {T} type - Transaction type * @param {Provider} provider - Provider @@ -46,8 +51,6 @@ export class TransactionListener this.type = type this.filter = filter this.provider = provider ?? Provider.instance - // @ts-expect-error allow dynamic access - this[TransactionListenerProcessIndex[type]]() } /** @@ -55,7 +58,10 @@ export class TransactionListener * @returns {void} */ stop(): void { - // Close the listener + if (this.status) { + this.status = false + // stop the listener + } } /** @@ -63,7 +69,11 @@ export class TransactionListener * @returns {void} */ start(): void { - // Start the listener + if (!this.status) { + this.status = true + // @ts-expect-error allow dynamic access + this[TransactionListenerProcessIndex[this.type]]() + } } /** @@ -88,10 +98,13 @@ export class TransactionListener * @param {DynamicTransactionType} transaction - Transaction data * @returns {void} */ - trigger(transaction: DynamicTransactionType): void { - this.callbacks.forEach((callback) => { - callback(transaction) - }) + trigger(transaction: DynamicTransactionType): void { + if (!this.triggeredTransactions.includes(transaction.id)) { + this.triggeredTransactions.push(transaction.id) + this.callbacks.forEach((callback) => { + callback(transaction) + }) + } } /** From 54012e472ec015672aa5c5219d4bf04ee8e600a7 Mon Sep 17 00:00:00 2001 From: Halil Beycan <50718965+BeycanDeveloper@users.noreply.github.com> Date: Sun, 31 Mar 2024 23:32:08 +0800 Subject: [PATCH 084/114] completed index files --- packages/networks/boilerplate/src/index.ts | 32 ++++++++++++++++++++++ packages/networks/evm-chains/src/index.ts | 32 ++++++++++++++++++++++ 2 files changed, 64 insertions(+) diff --git a/packages/networks/boilerplate/src/index.ts b/packages/networks/boilerplate/src/index.ts index e69de29..3d92bbb 100644 --- a/packages/networks/boilerplate/src/index.ts +++ b/packages/networks/boilerplate/src/index.ts @@ -0,0 +1,32 @@ +import * as NFT from './assets/NFT.ts' +import * as Coin from './assets/Coin.ts' +import * as Token from './assets/Token.ts' +import * as Contract from './assets/Contract.ts' + +import * as Transaction from './models/Transaction.ts' +import * as NftTransaction from './models/NftTransaction.ts' +import * as CoinTransaction from './models/CoinTransaction.ts' +import * as TokenTransaction from './models/TokenTransaction.ts' +import * as ContractTransaction from './models/ContractTransaction.ts' + +export * as utils from '@multiplechain/utils' +export * as types from '@multiplechain/types' + +export * as Provider from './services/Provider.ts' +export * as TransactionSigner from './services/TransactionSigner.ts' +export * as TransactionListener from './services/TransactionListener.ts' + +export const assets = { + NFT, + Coin, + Token, + Contract +} + +export const models = { + Transaction, + NftTransaction, + CoinTransaction, + TokenTransaction, + ContractTransaction +} diff --git a/packages/networks/evm-chains/src/index.ts b/packages/networks/evm-chains/src/index.ts index e69de29..3d92bbb 100644 --- a/packages/networks/evm-chains/src/index.ts +++ b/packages/networks/evm-chains/src/index.ts @@ -0,0 +1,32 @@ +import * as NFT from './assets/NFT.ts' +import * as Coin from './assets/Coin.ts' +import * as Token from './assets/Token.ts' +import * as Contract from './assets/Contract.ts' + +import * as Transaction from './models/Transaction.ts' +import * as NftTransaction from './models/NftTransaction.ts' +import * as CoinTransaction from './models/CoinTransaction.ts' +import * as TokenTransaction from './models/TokenTransaction.ts' +import * as ContractTransaction from './models/ContractTransaction.ts' + +export * as utils from '@multiplechain/utils' +export * as types from '@multiplechain/types' + +export * as Provider from './services/Provider.ts' +export * as TransactionSigner from './services/TransactionSigner.ts' +export * as TransactionListener from './services/TransactionListener.ts' + +export const assets = { + NFT, + Coin, + Token, + Contract +} + +export const models = { + Transaction, + NftTransaction, + CoinTransaction, + TokenTransaction, + ContractTransaction +} From c4c0b5d649651f4a42faf14228906db0d15e3ff2 Mon Sep 17 00:00:00 2001 From: Halil Beycan <50718965+BeycanDeveloper@users.noreply.github.com> Date: Mon, 1 Apr 2024 00:23:30 +0800 Subject: [PATCH 085/114] configured build options --- packages/networks/evm-chains/README.md | 1 + packages/networks/evm-chains/package.json | 18 ++++++++++++++---- .../networks/evm-chains/tests/assets.spec.ts | 2 +- packages/networks/evm-chains/vite.config.ts | 10 ++++++++++ 4 files changed, 26 insertions(+), 5 deletions(-) create mode 100644 packages/networks/evm-chains/vite.config.ts diff --git a/packages/networks/evm-chains/README.md b/packages/networks/evm-chains/README.md index e69de29..6ae2ea3 100644 --- a/packages/networks/evm-chains/README.md +++ b/packages/networks/evm-chains/README.md @@ -0,0 +1 @@ +Preparing \ No newline at end of file diff --git a/packages/networks/evm-chains/package.json b/packages/networks/evm-chains/package.json index 6789218..e00bb6d 100644 --- a/packages/networks/evm-chains/package.json +++ b/packages/networks/evm-chains/package.json @@ -1,9 +1,19 @@ { "name": "@multiplechain/evm-chains", - "version": "0.3.5", + "version": "0.3.31", "type": "module", - "main": "./dist/esm/index.js", - "types": "./dist/types/index.d.ts", + "types": "dist/index.d.ts", + "main": "dist/index.cjs.js", + "module": "dist/index.es.js", + "unpkg": "dist/index.umd.js", + "browser": "dist/index.umd.js", + "jsdelivr": "dist/index.umd.js", + "exports": { + ".": { + "import": "./dist/index.es.js", + "require": "./dist/index.cjs.js" + } + }, "files": [ "dist", "README.md", @@ -11,7 +21,7 @@ ], "scripts": { "clean": "rm -rf dist", - "build": "tsc --build", + "build": "vite build", "watch": "tsc --watch", "typecheck": "tsc --noEmit", "lint": "eslint . --ext .ts", diff --git a/packages/networks/evm-chains/tests/assets.spec.ts b/packages/networks/evm-chains/tests/assets.spec.ts index d2c38ab..5b6a798 100644 --- a/packages/networks/evm-chains/tests/assets.spec.ts +++ b/packages/networks/evm-chains/tests/assets.spec.ts @@ -12,7 +12,7 @@ const coinTransferTestIsActive = false const tokenTransferTestIsActive = false const tokenApproveTestIsActive = false const tokenTransferFromTestIsActive = false -const nftTransactionTestIsActive = true +const nftTransactionTestIsActive = false const balanceTestAddress = '0x760A4d3D03928D1e8541A7644B34370c1b79aa9F' const coinBalanceTestAmount = 0.01 diff --git a/packages/networks/evm-chains/vite.config.ts b/packages/networks/evm-chains/vite.config.ts new file mode 100644 index 0000000..342217d --- /dev/null +++ b/packages/networks/evm-chains/vite.config.ts @@ -0,0 +1,10 @@ +import { mergeConfig } from 'vite' +import mainConfig from '../../../vite.config.ts' + +export default mergeConfig(mainConfig, { + build: { + lib: { + name: 'EvmChains' + } + } +}) From 8174b9266a49bb9feafeada788f32fee5ac37dfc Mon Sep 17 00:00:00 2001 From: Halil Beycan <50718965+BeycanDeveloper@users.noreply.github.com> Date: Mon, 1 Apr 2024 00:23:40 +0800 Subject: [PATCH 086/114] configured build options --- package.json | 1 + packages/networks/boilerplate/vite.config.ts | 10 + pnpm-lock.yaml | 723 ++++++++++--------- tsconfig.json | 1 + vite.config.ts | 29 +- 5 files changed, 405 insertions(+), 359 deletions(-) create mode 100644 packages/networks/boilerplate/vite.config.ts diff --git a/package.json b/package.json index 2b86cd2..fea9d15 100644 --- a/package.json +++ b/package.json @@ -27,6 +27,7 @@ "prettier": "^3.2.5", "typescript": "^5.3.3", "vite": "^5.1.4", + "vite-plugin-dts": "^3.8.1", "vite-plugin-node-polyfills": "^0.21.0", "vitest": "^1.3.1" } diff --git a/packages/networks/boilerplate/vite.config.ts b/packages/networks/boilerplate/vite.config.ts new file mode 100644 index 0000000..ddc52ce --- /dev/null +++ b/packages/networks/boilerplate/vite.config.ts @@ -0,0 +1,10 @@ +import { mergeConfig } from 'vite' +import mainConfig from '../../../vite.config.ts' + +export default mergeConfig(mainConfig, { + build: { + lib: { + name: 'Boilerplate' + } + } +}) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 21409da..fd4d087 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -4,14 +4,6 @@ settings: autoInstallPeers: true excludeLinksFromLockfile: false -dependencies: - abi-decoder: - specifier: ^2.4.0 - version: 2.4.0 - ethers: - specifier: ^6.11.1 - version: 6.11.1 - devDependencies: '@types/node': specifier: ^20.11.20 @@ -58,6 +50,9 @@ devDependencies: vite: specifier: ^5.1.4 version: 5.1.4(@types/node@20.11.20) + vite-plugin-dts: + specifier: ^3.8.1 + version: 3.8.1(@types/node@20.11.20)(typescript@5.3.3)(vite@5.1.4) vite-plugin-node-polyfills: specifier: ^0.21.0 version: 0.21.0(vite@5.1.4) @@ -72,9 +67,32 @@ packages: engines: {node: '>=0.10.0'} dev: true - /@adraffy/ens-normalize@1.10.1: - resolution: {integrity: sha512-96Z2IP3mYmF1Xg2cDm8f1gWGf/HUVedQ3FMifV4kG/PQ4yEP51xDtRAEfhVNt5f/uzpNkZHwWQuUcu6D6K+Ekw==} - dev: false + /@babel/helper-string-parser@7.24.1: + resolution: {integrity: sha512-2ofRCjnnA9y+wk8b9IAREroeUP02KHp431N2mhKniy2yKIDKpbrHv9eXwm8cBeWQYcJmzv5qKCu65P47eCF7CQ==} + engines: {node: '>=6.9.0'} + dev: true + + /@babel/helper-validator-identifier@7.22.20: + resolution: {integrity: sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==} + engines: {node: '>=6.9.0'} + dev: true + + /@babel/parser@7.24.1: + resolution: {integrity: sha512-Zo9c7N3xdOIQrNip7Lc9wvRPzlRtovHVE4lkz8WEDr7uYh/GMQhSiIgFxGIArRHYdJE5kxtZjAf8rT0xhdLCzg==} + engines: {node: '>=6.0.0'} + hasBin: true + dependencies: + '@babel/types': 7.24.0 + dev: true + + /@babel/types@7.24.0: + resolution: {integrity: sha512-+j7a5c253RfKh8iABBhywc8NSfP5LURe7Uh4qpsh6jc+aLJguvmIUBdjSdEMQv2bENrCR5MfRdjGo7vzS/ob7w==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/helper-string-parser': 7.24.1 + '@babel/helper-validator-identifier': 7.22.20 + to-fast-properties: 2.0.0 + dev: true /@esbuild/aix-ppc64@0.19.12: resolution: {integrity: sha512-bmoCYyWdEL3wDQIVbcyzRyeKLgk2WtWLTWz1ZIAZF/EGbNOwSA6ew3PftJ1PqMiOOGu0OyFMzG53L0zqIpPeNA==} @@ -320,180 +338,6 @@ packages: engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} dev: true - /@ethereumjs/rlp@4.0.1: - resolution: {integrity: sha512-tqsQiBQDQdmPWE1xkkBq4rlSW5QZpLOUJ5RJh2/9fug+q9tnUhuZoVLk7s0scUIKTOzEtR72DFBXI4WiZcMpvw==} - engines: {node: '>=14'} - hasBin: true - dev: false - - /@ethereumjs/util@8.1.0: - resolution: {integrity: sha512-zQ0IqbdX8FZ9aw11vP+dZkKDkS+kgIvQPHnSAXzP9pLu+Rfu3D3XEeLbicvoXJTYnhZiPmsZUxgdzXwNKxRPbA==} - engines: {node: '>=14'} - dependencies: - '@ethereumjs/rlp': 4.0.1 - ethereum-cryptography: 2.1.3 - micro-ftch: 0.3.1 - dev: false - - /@ethersproject/abi@5.7.0: - resolution: {integrity: sha512-351ktp42TiRcYB3H1OP8yajPeAQstMW/yCFokj/AthP9bLHzQFPlOrxOcwYEDkUAICmOHljvN4K39OMTMUa9RA==} - dependencies: - '@ethersproject/address': 5.7.0 - '@ethersproject/bignumber': 5.7.0 - '@ethersproject/bytes': 5.7.0 - '@ethersproject/constants': 5.7.0 - '@ethersproject/hash': 5.7.0 - '@ethersproject/keccak256': 5.7.0 - '@ethersproject/logger': 5.7.0 - '@ethersproject/properties': 5.7.0 - '@ethersproject/strings': 5.7.0 - dev: false - - /@ethersproject/abstract-provider@5.7.0: - resolution: {integrity: sha512-R41c9UkchKCpAqStMYUpdunjo3pkEvZC3FAwZn5S5MGbXoMQOHIdHItezTETxAO5bevtMApSyEhn9+CHcDsWBw==} - dependencies: - '@ethersproject/bignumber': 5.7.0 - '@ethersproject/bytes': 5.7.0 - '@ethersproject/logger': 5.7.0 - '@ethersproject/networks': 5.7.1 - '@ethersproject/properties': 5.7.0 - '@ethersproject/transactions': 5.7.0 - '@ethersproject/web': 5.7.1 - dev: false - - /@ethersproject/abstract-signer@5.7.0: - resolution: {integrity: sha512-a16V8bq1/Cz+TGCkE2OPMTOUDLS3grCpdjoJCYNnVBbdYEMSgKrU0+B90s8b6H+ByYTBZN7a3g76jdIJi7UfKQ==} - dependencies: - '@ethersproject/abstract-provider': 5.7.0 - '@ethersproject/bignumber': 5.7.0 - '@ethersproject/bytes': 5.7.0 - '@ethersproject/logger': 5.7.0 - '@ethersproject/properties': 5.7.0 - dev: false - - /@ethersproject/address@5.7.0: - resolution: {integrity: sha512-9wYhYt7aghVGo758POM5nqcOMaE168Q6aRLJZwUmiqSrAungkG74gSSeKEIR7ukixesdRZGPgVqme6vmxs1fkA==} - dependencies: - '@ethersproject/bignumber': 5.7.0 - '@ethersproject/bytes': 5.7.0 - '@ethersproject/keccak256': 5.7.0 - '@ethersproject/logger': 5.7.0 - '@ethersproject/rlp': 5.7.0 - dev: false - - /@ethersproject/base64@5.7.0: - resolution: {integrity: sha512-Dr8tcHt2mEbsZr/mwTPIQAf3Ai0Bks/7gTw9dSqk1mQvhW3XvRlmDJr/4n+wg1JmCl16NZue17CDh8xb/vZ0sQ==} - dependencies: - '@ethersproject/bytes': 5.7.0 - dev: false - - /@ethersproject/bignumber@5.7.0: - resolution: {integrity: sha512-n1CAdIHRWjSucQO3MC1zPSVgV/6dy/fjL9pMrPP9peL+QxEg9wOsVqwD4+818B6LUEtaXzVHQiuivzRoxPxUGw==} - dependencies: - '@ethersproject/bytes': 5.7.0 - '@ethersproject/logger': 5.7.0 - bn.js: 5.2.1 - dev: false - - /@ethersproject/bytes@5.7.0: - resolution: {integrity: sha512-nsbxwgFXWh9NyYWo+U8atvmMsSdKJprTcICAkvbBffT75qDocbuggBU0SJiVK2MuTrp0q+xvLkTnGMPK1+uA9A==} - dependencies: - '@ethersproject/logger': 5.7.0 - dev: false - - /@ethersproject/constants@5.7.0: - resolution: {integrity: sha512-DHI+y5dBNvkpYUMiRQyxRBYBefZkJfo70VUkUAsRjcPs47muV9evftfZ0PJVCXYbAiCgght0DtcF9srFQmIgWA==} - dependencies: - '@ethersproject/bignumber': 5.7.0 - dev: false - - /@ethersproject/hash@5.7.0: - resolution: {integrity: sha512-qX5WrQfnah1EFnO5zJv1v46a8HW0+E5xuBBDTwMFZLuVTx0tbU2kkx15NqdjxecrLGatQN9FGQKpb1FKdHCt+g==} - dependencies: - '@ethersproject/abstract-signer': 5.7.0 - '@ethersproject/address': 5.7.0 - '@ethersproject/base64': 5.7.0 - '@ethersproject/bignumber': 5.7.0 - '@ethersproject/bytes': 5.7.0 - '@ethersproject/keccak256': 5.7.0 - '@ethersproject/logger': 5.7.0 - '@ethersproject/properties': 5.7.0 - '@ethersproject/strings': 5.7.0 - dev: false - - /@ethersproject/keccak256@5.7.0: - resolution: {integrity: sha512-2UcPboeL/iW+pSg6vZ6ydF8tCnv3Iu/8tUmLLzWWGzxWKFFqOBQFLo6uLUv6BDrLgCDfN28RJ/wtByx+jZ4KBg==} - dependencies: - '@ethersproject/bytes': 5.7.0 - js-sha3: 0.8.0 - dev: false - - /@ethersproject/logger@5.7.0: - resolution: {integrity: sha512-0odtFdXu/XHtjQXJYA3u9G0G8btm0ND5Cu8M7i5vhEcE8/HmF4Lbdqanwyv4uQTr2tx6b7fQRmgLrsnpQlmnig==} - dev: false - - /@ethersproject/networks@5.7.1: - resolution: {integrity: sha512-n/MufjFYv3yFcUyfhnXotyDlNdFb7onmkSy8aQERi2PjNcnWQ66xXxa3XlS8nCcA8aJKJjIIMNJTC7tu80GwpQ==} - dependencies: - '@ethersproject/logger': 5.7.0 - dev: false - - /@ethersproject/properties@5.7.0: - resolution: {integrity: sha512-J87jy8suntrAkIZtecpxEPxY//szqr1mlBaYlQ0r4RCaiD2hjheqF9s1LVE8vVuJCXisjIP+JgtK/Do54ej4Sw==} - dependencies: - '@ethersproject/logger': 5.7.0 - dev: false - - /@ethersproject/rlp@5.7.0: - resolution: {integrity: sha512-rBxzX2vK8mVF7b0Tol44t5Tb8gomOHkj5guL+HhzQ1yBh/ydjGnpw6at+X6Iw0Kp3OzzzkcKp8N9r0W4kYSs9w==} - dependencies: - '@ethersproject/bytes': 5.7.0 - '@ethersproject/logger': 5.7.0 - dev: false - - /@ethersproject/signing-key@5.7.0: - resolution: {integrity: sha512-MZdy2nL3wO0u7gkB4nA/pEf8lu1TlFswPNmy8AiYkfKTdO6eXBJyUdmHO/ehm/htHw9K/qF8ujnTyUAD+Ry54Q==} - dependencies: - '@ethersproject/bytes': 5.7.0 - '@ethersproject/logger': 5.7.0 - '@ethersproject/properties': 5.7.0 - bn.js: 5.2.1 - elliptic: 6.5.4 - hash.js: 1.1.7 - dev: false - - /@ethersproject/strings@5.7.0: - resolution: {integrity: sha512-/9nu+lj0YswRNSH0NXYqrh8775XNyEdUQAuf3f+SmOrnVewcJ5SBNAjF7lpgehKi4abvNNXyf+HX86czCdJ8Mg==} - dependencies: - '@ethersproject/bytes': 5.7.0 - '@ethersproject/constants': 5.7.0 - '@ethersproject/logger': 5.7.0 - dev: false - - /@ethersproject/transactions@5.7.0: - resolution: {integrity: sha512-kmcNicCp1lp8qanMTC3RIikGgoJ80ztTyvtsFvCYpSCfkjhD0jZ2LOrnbcuxuToLIUYYf+4XwD1rP+B/erDIhQ==} - dependencies: - '@ethersproject/address': 5.7.0 - '@ethersproject/bignumber': 5.7.0 - '@ethersproject/bytes': 5.7.0 - '@ethersproject/constants': 5.7.0 - '@ethersproject/keccak256': 5.7.0 - '@ethersproject/logger': 5.7.0 - '@ethersproject/properties': 5.7.0 - '@ethersproject/rlp': 5.7.0 - '@ethersproject/signing-key': 5.7.0 - dev: false - - /@ethersproject/web@5.7.1: - resolution: {integrity: sha512-Gueu8lSvyjBWL4cYsWsjh6MtMwM0+H4HvqFPZfB6dV8ctbP9zFAO73VG1cMWae0FLPCtz0peKPpZY8/ugJJX2w==} - dependencies: - '@ethersproject/base64': 5.7.0 - '@ethersproject/bytes': 5.7.0 - '@ethersproject/logger': 5.7.0 - '@ethersproject/properties': 5.7.0 - '@ethersproject/strings': 5.7.0 - dev: false - /@humanwhocodes/config-array@0.11.14: resolution: {integrity: sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==} engines: {node: '>=10.10.0'} @@ -525,27 +369,49 @@ packages: resolution: {integrity: sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==} dev: true - /@noble/curves@1.2.0: - resolution: {integrity: sha512-oYclrNgRaM9SsBUBVbb8M6DTV7ZHRTKugureoYEncY5c65HOmRzvSiTE3y5CYaPYJA/GVkrhXEoF0M3Ya9PMnw==} + /@microsoft/api-extractor-model@7.28.13(@types/node@20.11.20): + resolution: {integrity: sha512-39v/JyldX4MS9uzHcdfmjjfS6cYGAoXV+io8B5a338pkHiSt+gy2eXQ0Q7cGFJ7quSa1VqqlMdlPrB6sLR/cAw==} dependencies: - '@noble/hashes': 1.3.2 - dev: false + '@microsoft/tsdoc': 0.14.2 + '@microsoft/tsdoc-config': 0.16.2 + '@rushstack/node-core-library': 4.0.2(@types/node@20.11.20) + transitivePeerDependencies: + - '@types/node' + dev: true - /@noble/curves@1.3.0: - resolution: {integrity: sha512-t01iSXPuN+Eqzb4eBX0S5oubSqXbK/xXa1Ne18Hj8f9pStxztHCE2gfboSp/dZRLSqfuLpRK2nDXDK+W9puocA==} + /@microsoft/api-extractor@7.43.0(@types/node@20.11.20): + resolution: {integrity: sha512-GFhTcJpB+MI6FhvXEI9b2K0snulNLWHqC/BbcJtyNYcKUiw7l3Lgis5ApsYncJ0leALX7/of4XfmXk+maT111w==} + hasBin: true dependencies: - '@noble/hashes': 1.3.3 - dev: false + '@microsoft/api-extractor-model': 7.28.13(@types/node@20.11.20) + '@microsoft/tsdoc': 0.14.2 + '@microsoft/tsdoc-config': 0.16.2 + '@rushstack/node-core-library': 4.0.2(@types/node@20.11.20) + '@rushstack/rig-package': 0.5.2 + '@rushstack/terminal': 0.10.0(@types/node@20.11.20) + '@rushstack/ts-command-line': 4.19.1(@types/node@20.11.20) + lodash: 4.17.21 + minimatch: 3.0.8 + resolve: 1.22.8 + semver: 7.5.4 + source-map: 0.6.1 + typescript: 5.4.2 + transitivePeerDependencies: + - '@types/node' + dev: true - /@noble/hashes@1.3.2: - resolution: {integrity: sha512-MVC8EAQp7MvEcm30KWENFjgR+Mkmf+D189XJTkFIlwohU5hcBbn1ZkKq7KVTi2Hme3PMGF390DaL52beVrIihQ==} - engines: {node: '>= 16'} - dev: false + /@microsoft/tsdoc-config@0.16.2: + resolution: {integrity: sha512-OGiIzzoBLgWWR0UdRJX98oYO+XKGf7tiK4Zk6tQ/E4IJqGCe7dvkTvgDZV5cFJUzLGDOjeAXrnZoA6QkVySuxw==} + dependencies: + '@microsoft/tsdoc': 0.14.2 + ajv: 6.12.6 + jju: 1.4.0 + resolve: 1.19.0 + dev: true - /@noble/hashes@1.3.3: - resolution: {integrity: sha512-V7/fPHgl+jsVPXqqeOzT8egNj2iBIVt+ECeMMG8TdcnTikP3oaBtUVqpT/gYCR68aEBJSF+XbYUxStjbFMqIIA==} - engines: {node: '>= 16'} - dev: false + /@microsoft/tsdoc@0.14.2: + resolution: {integrity: sha512-9b8mPpKrfeGRuhFH5iO1iwCLeIIsV6+H1sRfxbkoGXIyQE2BTsPd9zqSqQJ+pv5sJ/hT5M1zvOFL02MnEezFug==} + dev: true /@nodelib/fs.scandir@2.1.5: resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} @@ -705,29 +571,62 @@ packages: dev: true optional: true - /@scure/base@1.1.5: - resolution: {integrity: sha512-Brj9FiG2W1MRQSTB212YVPRrcbjkv48FoZi/u4l/zds/ieRrqsh7aUf6CLwkAq61oKXr/ZlTzlY66gLIj3TFTQ==} - dev: false + /@rushstack/node-core-library@4.0.2(@types/node@20.11.20): + resolution: {integrity: sha512-hyES82QVpkfQMeBMteQUnrhASL/KHPhd7iJ8euduwNJG4mu2GSOKybf0rOEjOm1Wz7CwJEUm9y0yD7jg2C1bfg==} + peerDependencies: + '@types/node': '*' + peerDependenciesMeta: + '@types/node': + optional: true + dependencies: + '@types/node': 20.11.20 + fs-extra: 7.0.1 + import-lazy: 4.0.0 + jju: 1.4.0 + resolve: 1.22.8 + semver: 7.5.4 + z-schema: 5.0.5 + dev: true - /@scure/bip32@1.3.3: - resolution: {integrity: sha512-LJaN3HwRbfQK0X1xFSi0Q9amqOgzQnnDngIt+ZlsBC3Bm7/nE7K0kwshZHyaru79yIVRv/e1mQAjZyuZG6jOFQ==} + /@rushstack/rig-package@0.5.2: + resolution: {integrity: sha512-mUDecIJeH3yYGZs2a48k+pbhM6JYwWlgjs2Ca5f2n1G2/kgdgP9D/07oglEGf6mRyXEnazhEENeYTSNDRCwdqA==} dependencies: - '@noble/curves': 1.3.0 - '@noble/hashes': 1.3.3 - '@scure/base': 1.1.5 - dev: false + resolve: 1.22.8 + strip-json-comments: 3.1.1 + dev: true - /@scure/bip39@1.2.2: - resolution: {integrity: sha512-HYf9TUXG80beW+hGAt3TRM8wU6pQoYur9iNypTROm42dorCGmLnFe3eWjz3gOq6G62H2WRh0FCzAR1PI+29zIA==} + /@rushstack/terminal@0.10.0(@types/node@20.11.20): + resolution: {integrity: sha512-UbELbXnUdc7EKwfH2sb8ChqNgapUOdqcCIdQP4NGxBpTZV2sQyeekuK3zmfQSa/MN+/7b4kBogl2wq0vpkpYGw==} + peerDependencies: + '@types/node': '*' + peerDependenciesMeta: + '@types/node': + optional: true dependencies: - '@noble/hashes': 1.3.3 - '@scure/base': 1.1.5 - dev: false + '@rushstack/node-core-library': 4.0.2(@types/node@20.11.20) + '@types/node': 20.11.20 + supports-color: 8.1.1 + dev: true + + /@rushstack/ts-command-line@4.19.1(@types/node@20.11.20): + resolution: {integrity: sha512-J7H768dgcpG60d7skZ5uSSwyCZs/S2HrWP1Ds8d1qYAyaaeJmpmmLr9BVw97RjFzmQPOYnoXcKA4GkqDCkduQg==} + dependencies: + '@rushstack/terminal': 0.10.0(@types/node@20.11.20) + '@types/argparse': 1.0.38 + argparse: 1.0.10 + string-argv: 0.3.2 + transitivePeerDependencies: + - '@types/node' + dev: true /@sinclair/typebox@0.27.8: resolution: {integrity: sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==} dev: true + /@types/argparse@1.0.38: + resolution: {integrity: sha512-ebDJ9b0e702Yr7pWgB0jzm+CX4Srzz8RcXtLJDJB+BSccqMa36uyH/zUsSYao5+BD1ytv3k3rPYCq4mAE1hsXA==} + dev: true + /@types/estree@1.0.5: resolution: {integrity: sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==} dev: true @@ -740,10 +639,6 @@ packages: resolution: {integrity: sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==} dev: true - /@types/node@18.15.13: - resolution: {integrity: sha512-N+0kuo9KgrUQ1Sn/ifDXsvg0TTleP7rIy4zOBGECxAljqvqfqpTfzx0Q1NUedOixRMBfe2Whhb056a42cWs26Q==} - dev: false - /@types/node@20.11.20: resolution: {integrity: sha512-7/rR21OS+fq8IyHTgtLkDK949uzsa6n8BkziAKtPVpugIkO6D+/ooXMvzXxDnZrmtXVfjb1bKQafYpb8s89LOg==} dependencies: @@ -929,12 +824,65 @@ packages: pretty-format: 29.7.0 dev: true - /abi-decoder@2.4.0: - resolution: {integrity: sha512-TOLU2q1HgYOjs1GKGtVzaqrYkar6I2fT9a80rzx6/9EJ/5crb4nCGuro0grZayixem93T7omrajYmLiMkYDLDA==} + /@volar/language-core@1.11.1: + resolution: {integrity: sha512-dOcNn3i9GgZAcJt43wuaEykSluAuOkQgzni1cuxLxTV0nJKanQztp7FxyswdRILaKH+P2XZMPRp2S4MV/pElCw==} + dependencies: + '@volar/source-map': 1.11.1 + dev: true + + /@volar/source-map@1.11.1: + resolution: {integrity: sha512-hJnOnwZ4+WT5iupLRnuzbULZ42L7BWWPMmruzwtLhJfpDVoZLjNBxHDi2sY2bgZXCKlpU5XcsMFoYrsQmPhfZg==} + dependencies: + muggle-string: 0.3.1 + dev: true + + /@volar/typescript@1.11.1: + resolution: {integrity: sha512-iU+t2mas/4lYierSnoFOeRFQUhAEMgsFuQxoxvwn5EdQopw43j+J27a4lt9LMInx1gLJBC6qL14WYGlgymaSMQ==} + dependencies: + '@volar/language-core': 1.11.1 + path-browserify: 1.0.1 + dev: true + + /@vue/compiler-core@3.4.21: + resolution: {integrity: sha512-MjXawxZf2SbZszLPYxaFCjxfibYrzr3eYbKxwpLR9EQN+oaziSu3qKVbwBERj1IFIB8OLUewxB5m/BFzi613og==} dependencies: - web3-eth-abi: 1.10.4 - web3-utils: 1.10.4 - dev: false + '@babel/parser': 7.24.1 + '@vue/shared': 3.4.21 + entities: 4.5.0 + estree-walker: 2.0.2 + source-map-js: 1.0.2 + dev: true + + /@vue/compiler-dom@3.4.21: + resolution: {integrity: sha512-IZC6FKowtT1sl0CR5DpXSiEB5ayw75oT2bma1BEhV7RRR1+cfwLrxc2Z8Zq/RGFzJ8w5r9QtCOvTjQgdn0IKmA==} + dependencies: + '@vue/compiler-core': 3.4.21 + '@vue/shared': 3.4.21 + dev: true + + /@vue/language-core@1.8.27(typescript@5.3.3): + resolution: {integrity: sha512-L8Kc27VdQserNaCUNiSFdDl9LWT24ly8Hpwf1ECy3aFb9m6bDhBGQYOujDm21N7EW3moKIOKEanQwe1q5BK+mA==} + peerDependencies: + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + dependencies: + '@volar/language-core': 1.11.1 + '@volar/source-map': 1.11.1 + '@vue/compiler-dom': 3.4.21 + '@vue/shared': 3.4.21 + computeds: 0.0.1 + minimatch: 9.0.3 + muggle-string: 0.3.1 + path-browserify: 1.0.1 + typescript: 5.3.3 + vue-template-compiler: 2.7.16 + dev: true + + /@vue/shared@3.4.21: + resolution: {integrity: sha512-PuJe7vDIi6VYSinuEbUIQgMIRZGgM8e4R+G+/dQTk0X1NEdvgvvgv7m+rfmDH1gZzyA1OjjoWskvHlfRNfQf3g==} + dev: true /acorn-jsx@5.3.2(acorn@8.11.3): resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} @@ -955,10 +903,6 @@ packages: hasBin: true dev: true - /aes-js@4.0.0-beta.5: - resolution: {integrity: sha512-G965FqalsNyrPqgEGON7nIx1e/OVENSgiEIzyC63haUMuvNnwIgIjMs52hlTCKhkBny7A2ORNlfY9Zu+jmGk1Q==} - dev: false - /agent-base@7.1.0: resolution: {integrity: sha512-o/zjMZRhJxny7OyEF+Op8X+efiELC7k7yOjMzgfzVqOzXqkBkWI79YoTdOtsuWd5BWhAGAuOY/Xa6xpiaWXiNg==} engines: {node: '>= 14'} @@ -994,6 +938,12 @@ packages: engines: {node: '>=10'} dev: true + /argparse@1.0.10: + resolution: {integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==} + dependencies: + sprintf-js: 1.0.3 + dev: true + /argparse@2.0.1: resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} dev: true @@ -1120,15 +1070,13 @@ packages: resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} dev: true - /bn.js@4.11.6: - resolution: {integrity: sha512-XWwnNNFCuuSQ0m3r3C4LE3EiORltHd9M05pq6FOlVeiophzRbMo50Sbz1ehl8K3Z+jw9+vmgnXefY1hz8X+2wA==} - dev: false - /bn.js@4.12.0: resolution: {integrity: sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==} + dev: true /bn.js@5.2.1: resolution: {integrity: sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ==} + dev: true /brace-expansion@1.1.11: resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} @@ -1152,6 +1100,7 @@ packages: /brorand@1.1.0: resolution: {integrity: sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w==} + dev: true /browser-resolve@2.0.0: resolution: {integrity: sha512-7sWsQlYL2rGLy2IWm8WL8DCTJvYLc/qlOnsakDac87SOoCd16WLsaAMdCiAqsTNHIe+SXfaqyxyo6THoWqs8WQ==} @@ -1314,6 +1263,17 @@ packages: delayed-stream: 1.0.0 dev: true + /commander@9.5.0: + resolution: {integrity: sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==} + engines: {node: ^12.20.0 || >=14} + requiresBuild: true + dev: true + optional: true + + /computeds@0.0.1: + resolution: {integrity: sha512-7CEBgcMjVmitjYo5q8JTJVra6X5mQ20uTThdK+0kR7UEaDrAWEQcRiBtWJzga4eRpP6afNwwLsX2SET2JhVB1Q==} + dev: true + /concat-map@0.0.1: resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} dev: true @@ -1398,6 +1358,10 @@ packages: whatwg-url: 14.0.0 dev: true + /de-indent@1.0.2: + resolution: {integrity: sha512-e/1zu3xH5MQryN2zdVaF0OrdNLUbvWxzMbi+iNA6Bky7l1RoP8a2fIbRocyHclXt/arDrrR6lL3TqFD9pMQTsg==} + dev: true + /debug@3.2.7: resolution: {integrity: sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==} peerDependencies: @@ -1515,6 +1479,7 @@ packages: inherits: 2.0.4 minimalistic-assert: 1.0.1 minimalistic-crypto-utils: 1.0.1 + dev: true /entities@4.5.0: resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==} @@ -1959,45 +1924,6 @@ packages: engines: {node: '>=0.10.0'} dev: true - /ethereum-bloom-filters@1.0.10: - resolution: {integrity: sha512-rxJ5OFN3RwjQxDcFP2Z5+Q9ho4eIdEmSc2ht0fCu8Se9nbXjZ7/031uXoUYJ87KHCOdVeiUuwSnoS7hmYAGVHA==} - dependencies: - js-sha3: 0.8.0 - dev: false - - /ethereum-cryptography@2.1.3: - resolution: {integrity: sha512-BlwbIL7/P45W8FGW2r7LGuvoEZ+7PWsniMvQ4p5s2xCyw9tmaDlpfsN9HjAucbF+t/qpVHwZUisgfK24TCW8aA==} - dependencies: - '@noble/curves': 1.3.0 - '@noble/hashes': 1.3.3 - '@scure/bip32': 1.3.3 - '@scure/bip39': 1.2.2 - dev: false - - /ethers@6.11.1: - resolution: {integrity: sha512-mxTAE6wqJQAbp5QAe/+o+rXOID7Nw91OZXvgpjDa1r4fAbq2Nu314oEZSbjoRLacuCzs7kUC3clEvkCQowffGg==} - engines: {node: '>=14.0.0'} - dependencies: - '@adraffy/ens-normalize': 1.10.1 - '@noble/curves': 1.2.0 - '@noble/hashes': 1.3.2 - '@types/node': 18.15.13 - aes-js: 4.0.0-beta.5 - tslib: 2.4.0 - ws: 8.5.0 - transitivePeerDependencies: - - bufferutil - - utf-8-validate - dev: false - - /ethjs-unit@0.1.6: - resolution: {integrity: sha512-/Sn9Y0oKl0uqQuvgFk/zQgR7aw1g36qX/jzSQ5lSwlO0GigPymk4eGQfeNTD03w1dPOqfz8V77Cy43jH56pagw==} - engines: {node: '>=6.5.0', npm: '>=3'} - dependencies: - bn.js: 4.11.6 - number-to-bn: 1.7.0 - dev: false - /events@3.3.0: resolution: {integrity: sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==} engines: {node: '>=0.8.x'} @@ -2108,6 +2034,15 @@ packages: mime-types: 2.1.35 dev: true + /fs-extra@7.0.1: + resolution: {integrity: sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==} + engines: {node: '>=6 <7 || >=8'} + dependencies: + graceful-fs: 4.2.11 + jsonfile: 4.0.0 + universalify: 0.1.2 + dev: true + /fs.realpath@1.0.0: resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} dev: true @@ -2230,6 +2165,10 @@ packages: get-intrinsic: 1.2.4 dev: true + /graceful-fs@4.2.11: + resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} + dev: true + /graphemer@1.4.0: resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==} dev: true @@ -2280,6 +2219,7 @@ packages: dependencies: inherits: 2.0.4 minimalistic-assert: 1.0.1 + dev: true /hasown@2.0.1: resolution: {integrity: sha512-1/th4MHjnwncwXsIW6QMzlvYL9kG5e/CpVvLRZe4XPa8TOUNbCELqmvhDmnkNsAjwaG4+I8gJJL0JBvTTLO9qA==} @@ -2288,12 +2228,18 @@ packages: function-bind: 1.1.2 dev: true + /he@1.2.0: + resolution: {integrity: sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==} + hasBin: true + dev: true + /hmac-drbg@1.0.1: resolution: {integrity: sha512-Tti3gMqLdZfhOQY1Mzf/AanLiqh1WTiJgEj26ZuYQ9fbkLomzGchCws4FyrSd4VkpBfiNhaE1On+lOz894jvXg==} dependencies: hash.js: 1.1.7 minimalistic-assert: 1.0.1 minimalistic-crypto-utils: 1.0.1 + dev: true /html-encoding-sniffer@4.0.0: resolution: {integrity: sha512-Y22oTqIU4uuPgEemfz7NDJz6OeKf12Lsu+QC+s3BVpda64lTiMYCyGwg5ki4vFxkMwQdeZDl2adZoqUgdFuTgQ==} @@ -2355,6 +2301,11 @@ packages: resolve-from: 4.0.0 dev: true + /import-lazy@4.0.0: + resolution: {integrity: sha512-rKtvo6a868b5Hu3heneU+L4yEQ4jYKLtjpnPeUdK7h0yzXGmyBTypknlkCvHFBqfX9YlorEiMM6Dnq/5atfHkw==} + engines: {node: '>=8'} + dev: true + /imurmurhash@0.1.4: resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} engines: {node: '>=0.8.19'} @@ -2369,6 +2320,7 @@ packages: /inherits@2.0.4: resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} + dev: true /internal-slot@1.0.7: resolution: {integrity: sha512-NGnrKwXzSms2qUUih/ILZ5JBqNTSa1+ZmP6flaIp6KmSElgE9qdndzS3cqjrDovwFdmwsGsLdeFgB6suw+1e9g==} @@ -2453,11 +2405,6 @@ packages: is-extglob: 2.1.1 dev: true - /is-hex-prefixed@1.0.0: - resolution: {integrity: sha512-WvtOiug1VFrE9v1Cydwm+FnXd3+w9GaeVUss5W4v/SLy3UW00vP+6iNF2SdnfiBoLy4bTqVdkftNGTUeOFVsbA==} - engines: {node: '>=6.5.0', npm: '>=3'} - dev: false - /is-nan@1.3.2: resolution: {integrity: sha512-E+zBKpQ2t6MEo1VsonYmluk9NxGrbzpeeLC2xIViuO2EjU2xsXsBPwTr3Ykv9l08UYEVEdWeRZNouaZqF6RN0w==} engines: {node: '>= 0.4'} @@ -2552,9 +2499,9 @@ packages: engines: {node: '>=10'} dev: true - /js-sha3@0.8.0: - resolution: {integrity: sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q==} - dev: false + /jju@1.4.0: + resolution: {integrity: sha512-8wb9Yw966OSxApiCt0K3yNJL8pnNeIv+OEq2YMidz4FKP6nonSRoOXc80iXY4JaN2FC11B9qsNmDsm+ZOfMROA==} + dev: true /js-tokens@8.0.3: resolution: {integrity: sha512-UfJMcSJc+SEXEl9lH/VLHSZbThQyLpw1vLO1Lb+j4RWDvG3N2f7yj3PVQA3cmkTBNldJ9eFnM+xEXxHIXrYiJw==} @@ -2626,12 +2573,22 @@ packages: resolution: {integrity: sha512-AilxAyFOAcK5wA1+LeaySVBrHsGQvUFCDWXKpZjzaL0PqW+xfBOttn8GNtWKFWqneyMZj41MWF9Kl6iPWLwgOA==} dev: true + /jsonfile@4.0.0: + resolution: {integrity: sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==} + optionalDependencies: + graceful-fs: 4.2.11 + dev: true + /keyv@4.5.4: resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} dependencies: json-buffer: 3.0.1 dev: true + /kolorist@1.8.0: + resolution: {integrity: sha512-Y+60/zizpJ3HRH8DCss+q95yr6145JXZo46OTpFvDZWLfRCE4qChOyk1b26nMaNpfHHgxagk9dXT5OP0Tfe+dQ==} + dev: true + /levn@0.4.1: resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} engines: {node: '>= 0.8.0'} @@ -2659,6 +2616,14 @@ packages: resolution: {integrity: sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==} dev: true + /lodash.get@4.4.2: + resolution: {integrity: sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ==} + dev: true + + /lodash.isequal@4.5.0: + resolution: {integrity: sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==} + dev: true + /lodash.kebabcase@4.1.1: resolution: {integrity: sha512-N8XRTIMMqqDgSy4VLKPnJ/+hpGZN+PHQiJnSenYqPaVV/NCqEogTnAdZLQiGKhxX+JCs8waWq2t1XHWKOmlY8g==} dev: true @@ -2675,6 +2640,10 @@ packages: resolution: {integrity: sha512-sReKOYJIJf74dhJONhU4e0/shzi1trVbSWDOhKYE5XV2O+H7Sb2Dihwuc7xWxVl+DgFPyTqIN3zMfT9cq5iWDg==} dev: true + /lodash@4.17.21: + resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} + dev: true + /loupe@2.3.7: resolution: {integrity: sha512-zSMINGVYkdpYSOBmLi0D1Uo7JU9nVdQKrHxC8eYlV+9YKK9WePqAlL7lSlorG/U2Fw1w0hTBmaa/jrQ3UbPHtA==} dependencies: @@ -2695,6 +2664,13 @@ packages: '@jridgewell/sourcemap-codec': 1.4.15 dev: true + /magic-string@0.30.8: + resolution: {integrity: sha512-ISQTe55T2ao7XtlAStud6qwYPZjE4GK1S/BeVPus4jrq6JuOnQ00YKQC581RWhR122W7msZV263KzVeLoqidyQ==} + engines: {node: '>=12'} + dependencies: + '@jridgewell/sourcemap-codec': 1.4.15 + dev: true + /md5.js@1.3.5: resolution: {integrity: sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==} dependencies: @@ -2712,10 +2688,6 @@ packages: engines: {node: '>= 8'} dev: true - /micro-ftch@0.3.1: - resolution: {integrity: sha512-/0LLxhzP0tfiR5hcQebtudP56gUurs2CLkGarnCiB/OqEyUFQ6U3paQi/tgLv0hBJYt2rnr9MNpxz4fiiugstg==} - dev: false - /micromatch@4.0.5: resolution: {integrity: sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==} engines: {node: '>=8.6'} @@ -2751,9 +2723,17 @@ packages: /minimalistic-assert@1.0.1: resolution: {integrity: sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==} + dev: true /minimalistic-crypto-utils@1.0.1: resolution: {integrity: sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg==} + dev: true + + /minimatch@3.0.8: + resolution: {integrity: sha512-6FsRAQsxQ61mw+qP1ZzbL9Bc78x2p5OqNgNpnoAFLTrX8n5Kxph0CsnhmKKNXTWjXqU5L0pGPR7hYk+XWZr60Q==} + dependencies: + brace-expansion: 1.1.11 + dev: true /minimatch@3.1.2: resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} @@ -2785,6 +2765,10 @@ packages: resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==} dev: true + /muggle-string@0.3.1: + resolution: {integrity: sha512-ckmWDJjphvd/FvZawgygcUeQCxzvohjFO5RxTjj4eq8kw359gFF3E1brjfI+viLMxss5JrHTDRHZvu2/tuy0Qg==} + dev: true + /nanoid@3.3.7: resolution: {integrity: sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==} engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} @@ -2835,14 +2819,6 @@ packages: path-key: 4.0.0 dev: true - /number-to-bn@1.7.0: - resolution: {integrity: sha512-wsJ9gfSz1/s4ZsJN01lyonwuxA1tml6X1yBDnfpMglypcBRFZZkus26EdPSlqS5GJfYddVZa22p3VNb3z5m5Ig==} - engines: {node: '>=6.5.0', npm: '>=3'} - dependencies: - bn.js: 4.11.6 - strip-hex-prefix: 1.0.0 - dev: false - /nwsapi@2.2.7: resolution: {integrity: sha512-ub5E4+FBPKwAZx0UwIQOjYWGHTEq5sPqHQNRN8Z9e4A7u3Tj1weLJsL59yH9vmvqEtBHaOmT6cYQKIZOxp35FQ==} dev: true @@ -3149,6 +3125,7 @@ packages: resolution: {integrity: sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==} dependencies: safe-buffer: 5.2.1 + dev: true /randomfill@1.0.4: resolution: {integrity: sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==} @@ -3193,6 +3170,13 @@ packages: resolution: {integrity: sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==} dev: true + /resolve@1.19.0: + resolution: {integrity: sha512-rArEXAgsBG4UgRGcynxWIWKFvh/XZCcS8UJdHhwy91zwAvCZIbcs+vAbflgBnNjYMs/i/i+/Ux6IZhML1yPvxg==} + dependencies: + is-core-module: 2.13.1 + path-parse: 1.0.7 + dev: true + /resolve@1.22.8: resolution: {integrity: sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==} hasBin: true @@ -3266,6 +3250,7 @@ packages: /safe-buffer@5.2.1: resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} + dev: true /safe-regex-test@1.0.3: resolution: {integrity: sha512-CdASjNJPvRa7roO6Ra/gLYBTzYzzPyyBXxIMdGW3USQLyjWEls2RgW5UBTXaQVp+OrpeCK3bLem8smtmheoRuw==} @@ -3292,6 +3277,14 @@ packages: hasBin: true dev: true + /semver@7.5.4: + resolution: {integrity: sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==} + engines: {node: '>=10'} + hasBin: true + dependencies: + lru-cache: 6.0.0 + dev: true + /semver@7.6.0: resolution: {integrity: sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==} engines: {node: '>=10'} @@ -3375,6 +3368,15 @@ packages: engines: {node: '>=0.10.0'} dev: true + /source-map@0.6.1: + resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} + engines: {node: '>=0.10.0'} + dev: true + + /sprintf-js@1.0.3: + resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==} + dev: true + /stackback@0.0.2: resolution: {integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==} dev: true @@ -3399,6 +3401,11 @@ packages: xtend: 4.0.2 dev: true + /string-argv@0.3.2: + resolution: {integrity: sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q==} + engines: {node: '>=0.6.19'} + dev: true + /string.prototype.trim@1.2.8: resolution: {integrity: sha512-lfjY4HcixfQXOfaqCvcBuOIapyaroTXhbkfJN3gcB1OtyupngWK4sEET9Knd0cXd28kTUqu/kHoV4HKSJdnjiQ==} engines: {node: '>= 0.4'} @@ -3447,13 +3454,6 @@ packages: engines: {node: '>=12'} dev: true - /strip-hex-prefix@1.0.0: - resolution: {integrity: sha512-q8d4ue7JGEiVcypji1bALTos+0pWtyGlivAWyPuTkHzuTCJqrK9sWxYQZUq6Nq3cuyv3bm734IhHvHtGGURU6A==} - engines: {node: '>=6.5.0', npm: '>=3'} - dependencies: - is-hex-prefixed: 1.0.0 - dev: false - /strip-json-comments@3.1.1: resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} engines: {node: '>=8'} @@ -3472,6 +3472,13 @@ packages: has-flag: 4.0.0 dev: true + /supports-color@8.1.1: + resolution: {integrity: sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==} + engines: {node: '>=10'} + dependencies: + has-flag: 4.0.0 + dev: true + /supports-preserve-symlinks-flag@1.0.0: resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} engines: {node: '>= 0.4'} @@ -3514,6 +3521,11 @@ packages: engines: {node: '>=14.0.0'} dev: true + /to-fast-properties@2.0.0: + resolution: {integrity: sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==} + engines: {node: '>=4'} + dev: true + /to-regex-range@5.0.1: resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} engines: {node: '>=8.0'} @@ -3556,10 +3568,6 @@ packages: strip-bom: 3.0.0 dev: true - /tslib@2.4.0: - resolution: {integrity: sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==} - dev: false - /tslib@2.6.2: resolution: {integrity: sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==} dev: true @@ -3635,6 +3643,12 @@ packages: hasBin: true dev: true + /typescript@5.4.2: + resolution: {integrity: sha512-+2/g0Fds1ERlP6JsakQQDXjZdZMM+rqpamFZJEKh4kwTIn3iDkgKtby0CeNd5ATNZ4Ry1ax15TMx0W2V+miizQ==} + engines: {node: '>=14.17'} + hasBin: true + dev: true + /ufo@1.4.0: resolution: {integrity: sha512-Hhy+BhRBleFjpJ2vchUNN40qgkh0366FWJGqVLYBHev0vpHTrXSA0ryT+74UiW6KWsldNurQMKGqCm1M2zBciQ==} dev: true @@ -3652,6 +3666,11 @@ packages: resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==} dev: true + /universalify@0.1.2: + resolution: {integrity: sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==} + engines: {node: '>= 4.0.0'} + dev: true + /universalify@0.2.0: resolution: {integrity: sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==} engines: {node: '>= 4.0.0'} @@ -3677,10 +3696,6 @@ packages: qs: 6.11.2 dev: true - /utf8@3.0.0: - resolution: {integrity: sha512-E8VjFIQ/TyQgp+TZfS6l8yp/xWppSAHzidGiRrqe4bK4XP9pTRyKFgGJpO3SN7zdX4DeomTrwaseCHovfpFcqQ==} - dev: false - /util-deprecate@1.0.2: resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} dev: true @@ -3695,6 +3710,11 @@ packages: which-typed-array: 1.1.14 dev: true + /validator@13.11.0: + resolution: {integrity: sha512-Ii+sehpSfZy+At5nPdnyMhx78fEoPDkR2XW/zimHEL3MyGJQOCQ7WeP20jPYRz7ZCpcKLB21NxuXHF3bxjStBQ==} + engines: {node: '>= 0.10'} + dev: true + /vite-node@1.3.1(@types/node@20.11.20): resolution: {integrity: sha512-azbRrqRxlWTJEVbzInZCTchx0X69M/XPTCz4H+TLvlTcR/xH/3hkRqhOakT41fMJCMzXTu4UvegkZiEoJAWvng==} engines: {node: ^18.0.0 || >=20.0.0} @@ -3716,6 +3736,31 @@ packages: - terser dev: true + /vite-plugin-dts@3.8.1(@types/node@20.11.20)(typescript@5.3.3)(vite@5.1.4): + resolution: {integrity: sha512-zEYyQxH7lKto1VTKZHF3ZZeOPkkJgnMrePY4VxDHfDSvDjmYMMfWjZxYmNwW8QxbaItWJQhhXY+geAbyNphI7g==} + engines: {node: ^14.18.0 || >=16.0.0} + peerDependencies: + typescript: '*' + vite: '*' + peerDependenciesMeta: + vite: + optional: true + dependencies: + '@microsoft/api-extractor': 7.43.0(@types/node@20.11.20) + '@rollup/pluginutils': 5.1.0 + '@vue/language-core': 1.8.27(typescript@5.3.3) + debug: 4.3.4 + kolorist: 1.8.0 + magic-string: 0.30.8 + typescript: 5.3.3 + vite: 5.1.4(@types/node@20.11.20) + vue-tsc: 1.8.27(typescript@5.3.3) + transitivePeerDependencies: + - '@types/node' + - rollup + - supports-color + dev: true + /vite-plugin-node-polyfills@0.21.0(vite@5.1.4): resolution: {integrity: sha512-Sk4DiKnmxN8E0vhgEhzLudfJQfaT8k4/gJ25xvUPG54KjLJ6HAmDKbr4rzDD/QWEY+Lwg80KE85fGYBQihEPQA==} peerDependencies: @@ -3825,34 +3870,31 @@ packages: resolution: {integrity: sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ==} dev: true - /w3c-xmlserializer@5.0.0: - resolution: {integrity: sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA==} - engines: {node: '>=18'} + /vue-template-compiler@2.7.16: + resolution: {integrity: sha512-AYbUWAJHLGGQM7+cNTELw+KsOG9nl2CnSv467WobS5Cv9uk3wFcnr1Etsz2sEIHEZvw1U+o9mRlEO6QbZvUPGQ==} dependencies: - xml-name-validator: 5.0.0 + de-indent: 1.0.2 + he: 1.2.0 dev: true - /web3-eth-abi@1.10.4: - resolution: {integrity: sha512-cZ0q65eJIkd/jyOlQPDjr8X4fU6CRL1eWgdLwbWEpo++MPU/2P4PFk5ZLAdye9T5Sdp+MomePPJ/gHjLMj2VfQ==} - engines: {node: '>=8.0.0'} + /vue-tsc@1.8.27(typescript@5.3.3): + resolution: {integrity: sha512-WesKCAZCRAbmmhuGl3+VrdWItEvfoFIPXOvUJkjULi+x+6G/Dy69yO3TBRJDr9eUlmsNAwVmxsNZxvHKzbkKdg==} + hasBin: true + peerDependencies: + typescript: '*' dependencies: - '@ethersproject/abi': 5.7.0 - web3-utils: 1.10.4 - dev: false + '@volar/typescript': 1.11.1 + '@vue/language-core': 1.8.27(typescript@5.3.3) + semver: 7.6.0 + typescript: 5.3.3 + dev: true - /web3-utils@1.10.4: - resolution: {integrity: sha512-tsu8FiKJLk2PzhDl9fXbGUWTkkVXYhtTA+SmEFkKft+9BgwLxfCRpU96sWv7ICC8zixBNd3JURVoiR3dUXgP8A==} - engines: {node: '>=8.0.0'} + /w3c-xmlserializer@5.0.0: + resolution: {integrity: sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA==} + engines: {node: '>=18'} dependencies: - '@ethereumjs/util': 8.1.0 - bn.js: 5.2.1 - ethereum-bloom-filters: 1.0.10 - ethereum-cryptography: 2.1.3 - ethjs-unit: 0.1.6 - number-to-bn: 1.7.0 - randombytes: 2.1.0 - utf8: 3.0.0 - dev: false + xml-name-validator: 5.0.0 + dev: true /webidl-conversions@7.0.0: resolution: {integrity: sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==} @@ -3934,19 +3976,6 @@ packages: optional: true dev: true - /ws@8.5.0: - resolution: {integrity: sha512-BWX0SWVgLPzYwF8lTzEy1egjhS4S4OEAHfsO8o65WOVsrnSRGaSiUaa9e0ggGlkMTtBlmOpEXiie9RUcBO86qg==} - engines: {node: '>=10.0.0'} - peerDependencies: - bufferutil: ^4.0.1 - utf-8-validate: ^5.0.2 - peerDependenciesMeta: - bufferutil: - optional: true - utf-8-validate: - optional: true - dev: false - /xml-name-validator@5.0.0: resolution: {integrity: sha512-EvGK8EJ3DhaHfbRlETOWAS5pO9MZITeauHKJyb8wyajUfQUenkIg2MvLDTZ4T/TgIcm3HU0TFBgWWboAZ30UHg==} engines: {node: '>=18'} @@ -3974,3 +4003,15 @@ packages: resolution: {integrity: sha512-9bnSc/HEW2uRy67wc+T8UwauLuPJVn28jb+GtJY16iiKWyvmYJRXVT4UamsAEGQfPohgr2q4Tq0sQbQlxTfi1g==} engines: {node: '>=12.20'} dev: true + + /z-schema@5.0.5: + resolution: {integrity: sha512-D7eujBWkLa3p2sIpJA0d1pr7es+a7m0vFAnZLlCEKq/Ij2k0MLi9Br2UPxoxdYystm5K1yeBGzub0FlYUEWj2Q==} + engines: {node: '>=8.0.0'} + hasBin: true + dependencies: + lodash.get: 4.4.2 + lodash.isequal: 4.5.0 + validator: 13.11.0 + optionalDependencies: + commander: 9.5.0 + dev: true diff --git a/tsconfig.json b/tsconfig.json index baadf30..492dc24 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,5 +1,6 @@ { "compilerOptions": { + "declaration": true, "types": ["node"], "target": "ES2020", "useDefineForClassFields": true, diff --git a/vite.config.ts b/vite.config.ts index 6e367f1..c9d1e16 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -1,25 +1,18 @@ import { defineConfig } from 'vite' -import { nodePolyfills } from 'vite-plugin-node-polyfills' +import dts from 'vite-plugin-dts' -// https://vitejs.dev/config/ export default defineConfig({ - plugins: [nodePolyfills()], + plugins: [ + dts({ + entryRoot: './src' + }) + ], build: { - commonjsOptions: { - transformMixedEsModules: true - }, - assetsDir: '.', - assetsInlineLimit: 0, - rollupOptions: { - input: { - main: 'packages/main.ts' - }, - output: { - format: 'umd', - entryFileNames: 'app.min.js', - chunkFileNames: '[name].js', - assetFileNames: '[name].[ext]' - } + sourcemap: true, + lib: { + entry: './src/index.ts', + formats: ['es', 'cjs', 'umd'], + fileName: (format: string) => `index.${format}.js` } }, server: { From 96b9c2e904ed921969138b473f91d632384e4b46 Mon Sep 17 00:00:00 2001 From: Halil Beycan <50718965+BeycanDeveloper@users.noreply.github.com> Date: Mon, 1 Apr 2024 00:26:07 +0800 Subject: [PATCH 087/114] updated --- packages/networks/boilerplate/package.json | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/packages/networks/boilerplate/package.json b/packages/networks/boilerplate/package.json index 03ba2b6..c8134fe 100644 --- a/packages/networks/boilerplate/package.json +++ b/packages/networks/boilerplate/package.json @@ -1,9 +1,19 @@ { - "name": "@multiplechain/network-name", + "name": "@multiplechain/evm-chains", "version": "0.1.0", "type": "module", - "main": "./dist/esm/index.js", - "types": "./dist/types/index.d.ts", + "types": "dist/index.d.ts", + "main": "dist/index.cjs.js", + "module": "dist/index.es.js", + "unpkg": "dist/index.umd.js", + "browser": "dist/index.umd.js", + "jsdelivr": "dist/index.umd.js", + "exports": { + ".": { + "import": "./dist/index.es.js", + "require": "./dist/index.cjs.js" + } + }, "files": [ "dist", "README.md", @@ -11,7 +21,7 @@ ], "scripts": { "clean": "rm -rf dist", - "build": "tsc --build", + "build": "vite build", "watch": "tsc --watch", "typecheck": "tsc --noEmit", "lint": "eslint . --ext .ts", @@ -22,8 +32,7 @@ "web3", "crypto", "blockchain", - "multiple-chain", - "standard" + "multiple-chain" ], "author": "MultipleChain", "license": "MIT", From c80a4f5ac12f415810eeaa1c69b5cf4eabe1f0d2 Mon Sep 17 00:00:00 2001 From: Halil Beycan <50718965+BeycanDeveloper@users.noreply.github.com> Date: Mon, 1 Apr 2024 14:30:42 +0800 Subject: [PATCH 088/114] updated for easy use --- .../networks/boilerplate/src/assets/index.ts | 4 +++ packages/networks/boilerplate/src/index.ts | 32 +++---------------- .../networks/boilerplate/src/models/index.ts | 5 +++ .../boilerplate/src/services/index.ts | 2 ++ packages/networks/evm-chains/package.json | 2 +- .../networks/evm-chains/src/assets/index.ts | 4 +++ packages/networks/evm-chains/src/index.ts | 32 +++---------------- .../networks/evm-chains/src/models/index.ts | 5 +++ .../networks/evm-chains/src/services/index.ts | 2 ++ 9 files changed, 31 insertions(+), 57 deletions(-) create mode 100644 packages/networks/boilerplate/src/assets/index.ts create mode 100644 packages/networks/boilerplate/src/models/index.ts create mode 100644 packages/networks/boilerplate/src/services/index.ts create mode 100644 packages/networks/evm-chains/src/assets/index.ts create mode 100644 packages/networks/evm-chains/src/models/index.ts create mode 100644 packages/networks/evm-chains/src/services/index.ts diff --git a/packages/networks/boilerplate/src/assets/index.ts b/packages/networks/boilerplate/src/assets/index.ts new file mode 100644 index 0000000..7ea522f --- /dev/null +++ b/packages/networks/boilerplate/src/assets/index.ts @@ -0,0 +1,4 @@ +export * from './NFT.ts' +export * from './Coin.ts' +export * from './Token.ts' +export * from './Contract.ts' diff --git a/packages/networks/boilerplate/src/index.ts b/packages/networks/boilerplate/src/index.ts index 3d92bbb..668ab52 100644 --- a/packages/networks/boilerplate/src/index.ts +++ b/packages/networks/boilerplate/src/index.ts @@ -1,32 +1,8 @@ -import * as NFT from './assets/NFT.ts' -import * as Coin from './assets/Coin.ts' -import * as Token from './assets/Token.ts' -import * as Contract from './assets/Contract.ts' +export * from './services/Provider.ts' -import * as Transaction from './models/Transaction.ts' -import * as NftTransaction from './models/NftTransaction.ts' -import * as CoinTransaction from './models/CoinTransaction.ts' -import * as TokenTransaction from './models/TokenTransaction.ts' -import * as ContractTransaction from './models/ContractTransaction.ts' +export * as assets from './assets/index.ts' +export * as models from './models/index.ts' +export * as services from './services/index.ts' export * as utils from '@multiplechain/utils' export * as types from '@multiplechain/types' - -export * as Provider from './services/Provider.ts' -export * as TransactionSigner from './services/TransactionSigner.ts' -export * as TransactionListener from './services/TransactionListener.ts' - -export const assets = { - NFT, - Coin, - Token, - Contract -} - -export const models = { - Transaction, - NftTransaction, - CoinTransaction, - TokenTransaction, - ContractTransaction -} diff --git a/packages/networks/boilerplate/src/models/index.ts b/packages/networks/boilerplate/src/models/index.ts new file mode 100644 index 0000000..cc0a27c --- /dev/null +++ b/packages/networks/boilerplate/src/models/index.ts @@ -0,0 +1,5 @@ +export * from './Transaction.ts' +export * from './NftTransaction.ts' +export * from './CoinTransaction.ts' +export * from './TokenTransaction.ts' +export * from './ContractTransaction.ts' diff --git a/packages/networks/boilerplate/src/services/index.ts b/packages/networks/boilerplate/src/services/index.ts new file mode 100644 index 0000000..549a382 --- /dev/null +++ b/packages/networks/boilerplate/src/services/index.ts @@ -0,0 +1,2 @@ +export * from './TransactionSigner.ts' +export * from './TransactionListener.ts' diff --git a/packages/networks/evm-chains/package.json b/packages/networks/evm-chains/package.json index e00bb6d..ef59a17 100644 --- a/packages/networks/evm-chains/package.json +++ b/packages/networks/evm-chains/package.json @@ -1,6 +1,6 @@ { "name": "@multiplechain/evm-chains", - "version": "0.3.31", + "version": "0.3.34", "type": "module", "types": "dist/index.d.ts", "main": "dist/index.cjs.js", diff --git a/packages/networks/evm-chains/src/assets/index.ts b/packages/networks/evm-chains/src/assets/index.ts new file mode 100644 index 0000000..7ea522f --- /dev/null +++ b/packages/networks/evm-chains/src/assets/index.ts @@ -0,0 +1,4 @@ +export * from './NFT.ts' +export * from './Coin.ts' +export * from './Token.ts' +export * from './Contract.ts' diff --git a/packages/networks/evm-chains/src/index.ts b/packages/networks/evm-chains/src/index.ts index 3d92bbb..668ab52 100644 --- a/packages/networks/evm-chains/src/index.ts +++ b/packages/networks/evm-chains/src/index.ts @@ -1,32 +1,8 @@ -import * as NFT from './assets/NFT.ts' -import * as Coin from './assets/Coin.ts' -import * as Token from './assets/Token.ts' -import * as Contract from './assets/Contract.ts' +export * from './services/Provider.ts' -import * as Transaction from './models/Transaction.ts' -import * as NftTransaction from './models/NftTransaction.ts' -import * as CoinTransaction from './models/CoinTransaction.ts' -import * as TokenTransaction from './models/TokenTransaction.ts' -import * as ContractTransaction from './models/ContractTransaction.ts' +export * as assets from './assets/index.ts' +export * as models from './models/index.ts' +export * as services from './services/index.ts' export * as utils from '@multiplechain/utils' export * as types from '@multiplechain/types' - -export * as Provider from './services/Provider.ts' -export * as TransactionSigner from './services/TransactionSigner.ts' -export * as TransactionListener from './services/TransactionListener.ts' - -export const assets = { - NFT, - Coin, - Token, - Contract -} - -export const models = { - Transaction, - NftTransaction, - CoinTransaction, - TokenTransaction, - ContractTransaction -} diff --git a/packages/networks/evm-chains/src/models/index.ts b/packages/networks/evm-chains/src/models/index.ts new file mode 100644 index 0000000..cc0a27c --- /dev/null +++ b/packages/networks/evm-chains/src/models/index.ts @@ -0,0 +1,5 @@ +export * from './Transaction.ts' +export * from './NftTransaction.ts' +export * from './CoinTransaction.ts' +export * from './TokenTransaction.ts' +export * from './ContractTransaction.ts' diff --git a/packages/networks/evm-chains/src/services/index.ts b/packages/networks/evm-chains/src/services/index.ts new file mode 100644 index 0000000..549a382 --- /dev/null +++ b/packages/networks/evm-chains/src/services/index.ts @@ -0,0 +1,2 @@ +export * from './TransactionSigner.ts' +export * from './TransactionListener.ts' From efe93b25c4df5a5b4d0dd4fcead1d7261adfd28a Mon Sep 17 00:00:00 2001 From: Halil Beycan <50718965+BeycanDeveloper@users.noreply.github.com> Date: Mon, 1 Apr 2024 14:58:25 +0800 Subject: [PATCH 089/114] removed --- packages/networks/boilerplate/package.json | 1 - packages/networks/evm-chains/package.json | 1 - 2 files changed, 2 deletions(-) diff --git a/packages/networks/boilerplate/package.json b/packages/networks/boilerplate/package.json index c8134fe..b59cbeb 100644 --- a/packages/networks/boilerplate/package.json +++ b/packages/networks/boilerplate/package.json @@ -1,7 +1,6 @@ { "name": "@multiplechain/evm-chains", "version": "0.1.0", - "type": "module", "types": "dist/index.d.ts", "main": "dist/index.cjs.js", "module": "dist/index.es.js", diff --git a/packages/networks/evm-chains/package.json b/packages/networks/evm-chains/package.json index ef59a17..331170e 100644 --- a/packages/networks/evm-chains/package.json +++ b/packages/networks/evm-chains/package.json @@ -1,7 +1,6 @@ { "name": "@multiplechain/evm-chains", "version": "0.3.34", - "type": "module", "types": "dist/index.d.ts", "main": "dist/index.cjs.js", "module": "dist/index.es.js", From bf154be75ca5ab31a62243ce696ef73e86626210 Mon Sep 17 00:00:00 2001 From: Halil Beycan <50718965+BeycanDeveloper@users.noreply.github.com> Date: Mon, 1 Apr 2024 19:49:39 +0800 Subject: [PATCH 090/114] added esbuild for node side --- packages/networks/evm-chains/package.json | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/packages/networks/evm-chains/package.json b/packages/networks/evm-chains/package.json index 331170e..2976f8d 100644 --- a/packages/networks/evm-chains/package.json +++ b/packages/networks/evm-chains/package.json @@ -1,6 +1,7 @@ { "name": "@multiplechain/evm-chains", "version": "0.3.34", + "type": "module", "types": "dist/index.d.ts", "main": "dist/index.cjs.js", "module": "dist/index.es.js", @@ -20,12 +21,14 @@ ], "scripts": { "clean": "rm -rf dist", - "build": "vite build", "watch": "tsc --watch", + "build:vite": "vite build", "typecheck": "tsc --noEmit", "lint": "eslint . --ext .ts", "test": "vitest run --dir tests", - "prepublishOnly": "pnpm run build" + "prepublishOnly": "pnpm run build", + "build": "pnpm run build:vite && pnpm run build:node", + "build:node": "esbuild src/index.ts --bundle --platform=node --format=cjs --outfile=dist/index.cjs.js" }, "keywords": [ "web3", @@ -50,5 +53,8 @@ "@multiplechain/types": "^0.1.30", "@multiplechain/utils": "^0.1.10", "ethers": "^6.11.1" + }, + "devDependencies": { + "esbuild": "^0.20.2" } } \ No newline at end of file From d0bffcf95be81f879fc995a75dbdb7d31dbbf555 Mon Sep 17 00:00:00 2001 From: Halil Beycan <50718965+BeycanDeveloper@users.noreply.github.com> Date: Mon, 1 Apr 2024 19:49:47 +0800 Subject: [PATCH 091/114] updated --- package.json | 1 + packages/networks/boilerplate/package.json | 6 +- pnpm-lock.yaml | 241 +++++++++++++++++++++ vite.config.ts | 2 +- 4 files changed, 247 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index fea9d15..204ec27 100644 --- a/package.json +++ b/package.json @@ -14,6 +14,7 @@ "devDependencies": { "@types/node": "^20.11.20", "@typescript-eslint/eslint-plugin": "^6.21.0", + "esbuild": "^0.20.2", "eslint": "^8.57.0", "eslint-config-prettier": "^9.1.0", "eslint-config-standard-with-typescript": "^43.0.1", diff --git a/packages/networks/boilerplate/package.json b/packages/networks/boilerplate/package.json index b59cbeb..5d9b6a7 100644 --- a/packages/networks/boilerplate/package.json +++ b/packages/networks/boilerplate/package.json @@ -20,12 +20,14 @@ ], "scripts": { "clean": "rm -rf dist", - "build": "vite build", "watch": "tsc --watch", + "build:vite": "vite build", "typecheck": "tsc --noEmit", "lint": "eslint . --ext .ts", "test": "vitest run --dir tests", - "prepublishOnly": "pnpm run build" + "prepublishOnly": "pnpm run build", + "build": "pnpm run build:vite && pnpm run build:node", + "build:node": "esbuild src/index.ts --bundle --platform=node --format=cjs --outfile=dist/index.cjs.js" }, "keywords": [ "web3", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index fd4d087..807f5d2 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -11,6 +11,9 @@ devDependencies: '@typescript-eslint/eslint-plugin': specifier: ^6.21.0 version: 6.21.0(@typescript-eslint/parser@6.21.0)(eslint@8.57.0)(typescript@5.3.3) + esbuild: + specifier: ^0.20.2 + version: 0.20.2 eslint: specifier: ^8.57.0 version: 8.57.0 @@ -103,6 +106,15 @@ packages: dev: true optional: true + /@esbuild/aix-ppc64@0.20.2: + resolution: {integrity: sha512-D+EBOJHXdNZcLJRBkhENNG8Wji2kgc9AZ9KiPr1JuZjsNtyHzrsfLRrY0tk2H2aoFu6RANO1y1iPPUCDYWkb5g==} + engines: {node: '>=12'} + cpu: [ppc64] + os: [aix] + requiresBuild: true + dev: true + optional: true + /@esbuild/android-arm64@0.19.12: resolution: {integrity: sha512-P0UVNGIienjZv3f5zq0DP3Nt2IE/3plFzuaS96vihvD0Hd6H/q4WXUGpCxD/E8YrSXfNyRPbpTq+T8ZQioSuPA==} engines: {node: '>=12'} @@ -112,6 +124,15 @@ packages: dev: true optional: true + /@esbuild/android-arm64@0.20.2: + resolution: {integrity: sha512-mRzjLacRtl/tWU0SvD8lUEwb61yP9cqQo6noDZP/O8VkwafSYwZ4yWy24kan8jE/IMERpYncRt2dw438LP3Xmg==} + engines: {node: '>=12'} + cpu: [arm64] + os: [android] + requiresBuild: true + dev: true + optional: true + /@esbuild/android-arm@0.19.12: resolution: {integrity: sha512-qg/Lj1mu3CdQlDEEiWrlC4eaPZ1KztwGJ9B6J+/6G+/4ewxJg7gqj8eVYWvao1bXrqGiW2rsBZFSX3q2lcW05w==} engines: {node: '>=12'} @@ -121,6 +142,15 @@ packages: dev: true optional: true + /@esbuild/android-arm@0.20.2: + resolution: {integrity: sha512-t98Ra6pw2VaDhqNWO2Oph2LXbz/EJcnLmKLGBJwEwXX/JAN83Fym1rU8l0JUWK6HkIbWONCSSatf4sf2NBRx/w==} + engines: {node: '>=12'} + cpu: [arm] + os: [android] + requiresBuild: true + dev: true + optional: true + /@esbuild/android-x64@0.19.12: resolution: {integrity: sha512-3k7ZoUW6Q6YqhdhIaq/WZ7HwBpnFBlW905Fa4s4qWJyiNOgT1dOqDiVAQFwBH7gBRZr17gLrlFCRzF6jFh7Kew==} engines: {node: '>=12'} @@ -130,6 +160,15 @@ packages: dev: true optional: true + /@esbuild/android-x64@0.20.2: + resolution: {integrity: sha512-btzExgV+/lMGDDa194CcUQm53ncxzeBrWJcncOBxuC6ndBkKxnHdFJn86mCIgTELsooUmwUm9FkhSp5HYu00Rg==} + engines: {node: '>=12'} + cpu: [x64] + os: [android] + requiresBuild: true + dev: true + optional: true + /@esbuild/darwin-arm64@0.19.12: resolution: {integrity: sha512-B6IeSgZgtEzGC42jsI+YYu9Z3HKRxp8ZT3cqhvliEHovq8HSX2YX8lNocDn79gCKJXOSaEot9MVYky7AKjCs8g==} engines: {node: '>=12'} @@ -139,6 +178,15 @@ packages: dev: true optional: true + /@esbuild/darwin-arm64@0.20.2: + resolution: {integrity: sha512-4J6IRT+10J3aJH3l1yzEg9y3wkTDgDk7TSDFX+wKFiWjqWp/iCfLIYzGyasx9l0SAFPT1HwSCR+0w/h1ES/MjA==} + engines: {node: '>=12'} + cpu: [arm64] + os: [darwin] + requiresBuild: true + dev: true + optional: true + /@esbuild/darwin-x64@0.19.12: resolution: {integrity: sha512-hKoVkKzFiToTgn+41qGhsUJXFlIjxI/jSYeZf3ugemDYZldIXIxhvwN6erJGlX4t5h417iFuheZ7l+YVn05N3A==} engines: {node: '>=12'} @@ -148,6 +196,15 @@ packages: dev: true optional: true + /@esbuild/darwin-x64@0.20.2: + resolution: {integrity: sha512-tBcXp9KNphnNH0dfhv8KYkZhjc+H3XBkF5DKtswJblV7KlT9EI2+jeA8DgBjp908WEuYll6pF+UStUCfEpdysA==} + engines: {node: '>=12'} + cpu: [x64] + os: [darwin] + requiresBuild: true + dev: true + optional: true + /@esbuild/freebsd-arm64@0.19.12: resolution: {integrity: sha512-4aRvFIXmwAcDBw9AueDQ2YnGmz5L6obe5kmPT8Vd+/+x/JMVKCgdcRwH6APrbpNXsPz+K653Qg8HB/oXvXVukA==} engines: {node: '>=12'} @@ -157,6 +214,15 @@ packages: dev: true optional: true + /@esbuild/freebsd-arm64@0.20.2: + resolution: {integrity: sha512-d3qI41G4SuLiCGCFGUrKsSeTXyWG6yem1KcGZVS+3FYlYhtNoNgYrWcvkOoaqMhwXSMrZRl69ArHsGJ9mYdbbw==} + engines: {node: '>=12'} + cpu: [arm64] + os: [freebsd] + requiresBuild: true + dev: true + optional: true + /@esbuild/freebsd-x64@0.19.12: resolution: {integrity: sha512-EYoXZ4d8xtBoVN7CEwWY2IN4ho76xjYXqSXMNccFSx2lgqOG/1TBPW0yPx1bJZk94qu3tX0fycJeeQsKovA8gg==} engines: {node: '>=12'} @@ -166,6 +232,15 @@ packages: dev: true optional: true + /@esbuild/freebsd-x64@0.20.2: + resolution: {integrity: sha512-d+DipyvHRuqEeM5zDivKV1KuXn9WeRX6vqSqIDgwIfPQtwMP4jaDsQsDncjTDDsExT4lR/91OLjRo8bmC1e+Cw==} + engines: {node: '>=12'} + cpu: [x64] + os: [freebsd] + requiresBuild: true + dev: true + optional: true + /@esbuild/linux-arm64@0.19.12: resolution: {integrity: sha512-EoTjyYyLuVPfdPLsGVVVC8a0p1BFFvtpQDB/YLEhaXyf/5bczaGeN15QkR+O4S5LeJ92Tqotve7i1jn35qwvdA==} engines: {node: '>=12'} @@ -175,6 +250,15 @@ packages: dev: true optional: true + /@esbuild/linux-arm64@0.20.2: + resolution: {integrity: sha512-9pb6rBjGvTFNira2FLIWqDk/uaf42sSyLE8j1rnUpuzsODBq7FvpwHYZxQ/It/8b+QOS1RYfqgGFNLRI+qlq2A==} + engines: {node: '>=12'} + cpu: [arm64] + os: [linux] + requiresBuild: true + dev: true + optional: true + /@esbuild/linux-arm@0.19.12: resolution: {integrity: sha512-J5jPms//KhSNv+LO1S1TX1UWp1ucM6N6XuL6ITdKWElCu8wXP72l9MM0zDTzzeikVyqFE6U8YAV9/tFyj0ti+w==} engines: {node: '>=12'} @@ -184,6 +268,15 @@ packages: dev: true optional: true + /@esbuild/linux-arm@0.20.2: + resolution: {integrity: sha512-VhLPeR8HTMPccbuWWcEUD1Az68TqaTYyj6nfE4QByZIQEQVWBB8vup8PpR7y1QHL3CpcF6xd5WVBU/+SBEvGTg==} + engines: {node: '>=12'} + cpu: [arm] + os: [linux] + requiresBuild: true + dev: true + optional: true + /@esbuild/linux-ia32@0.19.12: resolution: {integrity: sha512-Thsa42rrP1+UIGaWz47uydHSBOgTUnwBwNq59khgIwktK6x60Hivfbux9iNR0eHCHzOLjLMLfUMLCypBkZXMHA==} engines: {node: '>=12'} @@ -193,6 +286,15 @@ packages: dev: true optional: true + /@esbuild/linux-ia32@0.20.2: + resolution: {integrity: sha512-o10utieEkNPFDZFQm9CoP7Tvb33UutoJqg3qKf1PWVeeJhJw0Q347PxMvBgVVFgouYLGIhFYG0UGdBumROyiig==} + engines: {node: '>=12'} + cpu: [ia32] + os: [linux] + requiresBuild: true + dev: true + optional: true + /@esbuild/linux-loong64@0.19.12: resolution: {integrity: sha512-LiXdXA0s3IqRRjm6rV6XaWATScKAXjI4R4LoDlvO7+yQqFdlr1Bax62sRwkVvRIrwXxvtYEHHI4dm50jAXkuAA==} engines: {node: '>=12'} @@ -202,6 +304,15 @@ packages: dev: true optional: true + /@esbuild/linux-loong64@0.20.2: + resolution: {integrity: sha512-PR7sp6R/UC4CFVomVINKJ80pMFlfDfMQMYynX7t1tNTeivQ6XdX5r2XovMmha/VjR1YN/HgHWsVcTRIMkymrgQ==} + engines: {node: '>=12'} + cpu: [loong64] + os: [linux] + requiresBuild: true + dev: true + optional: true + /@esbuild/linux-mips64el@0.19.12: resolution: {integrity: sha512-fEnAuj5VGTanfJ07ff0gOA6IPsvrVHLVb6Lyd1g2/ed67oU1eFzL0r9WL7ZzscD+/N6i3dWumGE1Un4f7Amf+w==} engines: {node: '>=12'} @@ -211,6 +322,15 @@ packages: dev: true optional: true + /@esbuild/linux-mips64el@0.20.2: + resolution: {integrity: sha512-4BlTqeutE/KnOiTG5Y6Sb/Hw6hsBOZapOVF6njAESHInhlQAghVVZL1ZpIctBOoTFbQyGW+LsVYZ8lSSB3wkjA==} + engines: {node: '>=12'} + cpu: [mips64el] + os: [linux] + requiresBuild: true + dev: true + optional: true + /@esbuild/linux-ppc64@0.19.12: resolution: {integrity: sha512-nYJA2/QPimDQOh1rKWedNOe3Gfc8PabU7HT3iXWtNUbRzXS9+vgB0Fjaqr//XNbd82mCxHzik2qotuI89cfixg==} engines: {node: '>=12'} @@ -220,6 +340,15 @@ packages: dev: true optional: true + /@esbuild/linux-ppc64@0.20.2: + resolution: {integrity: sha512-rD3KsaDprDcfajSKdn25ooz5J5/fWBylaaXkuotBDGnMnDP1Uv5DLAN/45qfnf3JDYyJv/ytGHQaziHUdyzaAg==} + engines: {node: '>=12'} + cpu: [ppc64] + os: [linux] + requiresBuild: true + dev: true + optional: true + /@esbuild/linux-riscv64@0.19.12: resolution: {integrity: sha512-2MueBrlPQCw5dVJJpQdUYgeqIzDQgw3QtiAHUC4RBz9FXPrskyyU3VI1hw7C0BSKB9OduwSJ79FTCqtGMWqJHg==} engines: {node: '>=12'} @@ -229,6 +358,15 @@ packages: dev: true optional: true + /@esbuild/linux-riscv64@0.20.2: + resolution: {integrity: sha512-snwmBKacKmwTMmhLlz/3aH1Q9T8v45bKYGE3j26TsaOVtjIag4wLfWSiZykXzXuE1kbCE+zJRmwp+ZbIHinnVg==} + engines: {node: '>=12'} + cpu: [riscv64] + os: [linux] + requiresBuild: true + dev: true + optional: true + /@esbuild/linux-s390x@0.19.12: resolution: {integrity: sha512-+Pil1Nv3Umes4m3AZKqA2anfhJiVmNCYkPchwFJNEJN5QxmTs1uzyy4TvmDrCRNT2ApwSari7ZIgrPeUx4UZDg==} engines: {node: '>=12'} @@ -238,6 +376,15 @@ packages: dev: true optional: true + /@esbuild/linux-s390x@0.20.2: + resolution: {integrity: sha512-wcWISOobRWNm3cezm5HOZcYz1sKoHLd8VL1dl309DiixxVFoFe/o8HnwuIwn6sXre88Nwj+VwZUvJf4AFxkyrQ==} + engines: {node: '>=12'} + cpu: [s390x] + os: [linux] + requiresBuild: true + dev: true + optional: true + /@esbuild/linux-x64@0.19.12: resolution: {integrity: sha512-B71g1QpxfwBvNrfyJdVDexenDIt1CiDN1TIXLbhOw0KhJzE78KIFGX6OJ9MrtC0oOqMWf+0xop4qEU8JrJTwCg==} engines: {node: '>=12'} @@ -247,6 +394,15 @@ packages: dev: true optional: true + /@esbuild/linux-x64@0.20.2: + resolution: {integrity: sha512-1MdwI6OOTsfQfek8sLwgyjOXAu+wKhLEoaOLTjbijk6E2WONYpH9ZU2mNtR+lZ2B4uwr+usqGuVfFT9tMtGvGw==} + engines: {node: '>=12'} + cpu: [x64] + os: [linux] + requiresBuild: true + dev: true + optional: true + /@esbuild/netbsd-x64@0.19.12: resolution: {integrity: sha512-3ltjQ7n1owJgFbuC61Oj++XhtzmymoCihNFgT84UAmJnxJfm4sYCiSLTXZtE00VWYpPMYc+ZQmB6xbSdVh0JWA==} engines: {node: '>=12'} @@ -256,6 +412,15 @@ packages: dev: true optional: true + /@esbuild/netbsd-x64@0.20.2: + resolution: {integrity: sha512-K8/DhBxcVQkzYc43yJXDSyjlFeHQJBiowJ0uVL6Tor3jGQfSGHNNJcWxNbOI8v5k82prYqzPuwkzHt3J1T1iZQ==} + engines: {node: '>=12'} + cpu: [x64] + os: [netbsd] + requiresBuild: true + dev: true + optional: true + /@esbuild/openbsd-x64@0.19.12: resolution: {integrity: sha512-RbrfTB9SWsr0kWmb9srfF+L933uMDdu9BIzdA7os2t0TXhCRjrQyCeOt6wVxr79CKD4c+p+YhCj31HBkYcXebw==} engines: {node: '>=12'} @@ -265,6 +430,15 @@ packages: dev: true optional: true + /@esbuild/openbsd-x64@0.20.2: + resolution: {integrity: sha512-eMpKlV0SThJmmJgiVyN9jTPJ2VBPquf6Kt/nAoo6DgHAoN57K15ZghiHaMvqjCye/uU4X5u3YSMgVBI1h3vKrQ==} + engines: {node: '>=12'} + cpu: [x64] + os: [openbsd] + requiresBuild: true + dev: true + optional: true + /@esbuild/sunos-x64@0.19.12: resolution: {integrity: sha512-HKjJwRrW8uWtCQnQOz9qcU3mUZhTUQvi56Q8DPTLLB+DawoiQdjsYq+j+D3s9I8VFtDr+F9CjgXKKC4ss89IeA==} engines: {node: '>=12'} @@ -274,6 +448,15 @@ packages: dev: true optional: true + /@esbuild/sunos-x64@0.20.2: + resolution: {integrity: sha512-2UyFtRC6cXLyejf/YEld4Hajo7UHILetzE1vsRcGL3earZEW77JxrFjH4Ez2qaTiEfMgAXxfAZCm1fvM/G/o8w==} + engines: {node: '>=12'} + cpu: [x64] + os: [sunos] + requiresBuild: true + dev: true + optional: true + /@esbuild/win32-arm64@0.19.12: resolution: {integrity: sha512-URgtR1dJnmGvX864pn1B2YUYNzjmXkuJOIqG2HdU62MVS4EHpU2946OZoTMnRUHklGtJdJZ33QfzdjGACXhn1A==} engines: {node: '>=12'} @@ -283,6 +466,15 @@ packages: dev: true optional: true + /@esbuild/win32-arm64@0.20.2: + resolution: {integrity: sha512-GRibxoawM9ZCnDxnP3usoUDO9vUkpAxIIZ6GQI+IlVmr5kP3zUq+l17xELTHMWTWzjxa2guPNyrpq1GWmPvcGQ==} + engines: {node: '>=12'} + cpu: [arm64] + os: [win32] + requiresBuild: true + dev: true + optional: true + /@esbuild/win32-ia32@0.19.12: resolution: {integrity: sha512-+ZOE6pUkMOJfmxmBZElNOx72NKpIa/HFOMGzu8fqzQJ5kgf6aTGrcJaFsNiVMH4JKpMipyK+7k0n2UXN7a8YKQ==} engines: {node: '>=12'} @@ -292,6 +484,15 @@ packages: dev: true optional: true + /@esbuild/win32-ia32@0.20.2: + resolution: {integrity: sha512-HfLOfn9YWmkSKRQqovpnITazdtquEW8/SoHW7pWpuEeguaZI4QnCRW6b+oZTztdBnZOS2hqJ6im/D5cPzBTTlQ==} + engines: {node: '>=12'} + cpu: [ia32] + os: [win32] + requiresBuild: true + dev: true + optional: true + /@esbuild/win32-x64@0.19.12: resolution: {integrity: sha512-T1QyPSDCyMXaO3pzBkF96E8xMkiRYbUEZADd29SyPGabqxMViNoii+NcK7eWJAEoU6RZyEm5lVSIjTmcdoB9HA==} engines: {node: '>=12'} @@ -301,6 +502,15 @@ packages: dev: true optional: true + /@esbuild/win32-x64@0.20.2: + resolution: {integrity: sha512-N49X4lJX27+l9jbLKSqZ6bKNjzQvHaT8IIFUy+YIqmXQdjYCToGWwOItDrfby14c78aDd5NHQl29xingXfCdLQ==} + engines: {node: '>=12'} + cpu: [x64] + os: [win32] + requiresBuild: true + dev: true + optional: true + /@eslint-community/eslint-utils@4.4.0(eslint@8.57.0): resolution: {integrity: sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -1604,6 +1814,37 @@ packages: '@esbuild/win32-x64': 0.19.12 dev: true + /esbuild@0.20.2: + resolution: {integrity: sha512-WdOOppmUNU+IbZ0PaDiTst80zjnrOkyJNHoKupIcVyU8Lvla3Ugx94VzkQ32Ijqd7UhHJy75gNWDMUekcrSJ6g==} + engines: {node: '>=12'} + hasBin: true + requiresBuild: true + optionalDependencies: + '@esbuild/aix-ppc64': 0.20.2 + '@esbuild/android-arm': 0.20.2 + '@esbuild/android-arm64': 0.20.2 + '@esbuild/android-x64': 0.20.2 + '@esbuild/darwin-arm64': 0.20.2 + '@esbuild/darwin-x64': 0.20.2 + '@esbuild/freebsd-arm64': 0.20.2 + '@esbuild/freebsd-x64': 0.20.2 + '@esbuild/linux-arm': 0.20.2 + '@esbuild/linux-arm64': 0.20.2 + '@esbuild/linux-ia32': 0.20.2 + '@esbuild/linux-loong64': 0.20.2 + '@esbuild/linux-mips64el': 0.20.2 + '@esbuild/linux-ppc64': 0.20.2 + '@esbuild/linux-riscv64': 0.20.2 + '@esbuild/linux-s390x': 0.20.2 + '@esbuild/linux-x64': 0.20.2 + '@esbuild/netbsd-x64': 0.20.2 + '@esbuild/openbsd-x64': 0.20.2 + '@esbuild/sunos-x64': 0.20.2 + '@esbuild/win32-arm64': 0.20.2 + '@esbuild/win32-ia32': 0.20.2 + '@esbuild/win32-x64': 0.20.2 + dev: true + /escape-string-regexp@4.0.0: resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} engines: {node: '>=10'} diff --git a/vite.config.ts b/vite.config.ts index c9d1e16..eb11468 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -11,7 +11,7 @@ export default defineConfig({ sourcemap: true, lib: { entry: './src/index.ts', - formats: ['es', 'cjs', 'umd'], + formats: ['es', 'umd'], fileName: (format: string) => `index.${format}.js` } }, From 9b4d56b784648e9f4d7d33d91f7ae573065daf85 Mon Sep 17 00:00:00 2001 From: Halil Beycan <50718965+BeycanDeveloper@users.noreply.github.com> Date: Mon, 1 Apr 2024 22:27:49 +0800 Subject: [PATCH 092/114] added websocket checker --- packages/utils/package.json | 2 +- packages/utils/src/index.ts | 28 ++++++++++++++++++++++++++++ 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/packages/utils/package.json b/packages/utils/package.json index a835704..ca3c759 100644 --- a/packages/utils/package.json +++ b/packages/utils/package.json @@ -1,6 +1,6 @@ { "name": "@multiplechain/utils", - "version": "0.1.10", + "version": "0.1.11", "type": "module", "main": "./src/index.ts", "types": "./src/index.ts", diff --git a/packages/utils/src/index.ts b/packages/utils/src/index.ts index 1bac426..0cf34d5 100644 --- a/packages/utils/src/index.ts +++ b/packages/utils/src/index.ts @@ -135,4 +135,32 @@ export const objectsEqual = (o1: any, o2: any): boolean => { return JSON.stringify(o1) === JSON.stringify(o2) } +/** + * checks if the given url is a valid websocket url + * @param {string} url + * @returns {Promise} + */ +export const checkWebSocket = async (url: string): Promise => { + return await new Promise((resolve, reject) => { + const socket = new WebSocket(url) + + socket.onopen = function () { + socket.close() + resolve(true) + } + + socket.onerror = function () { + reject(false) // eslint-disable-line + } + + socket.onclose = function (event) { + if (event.wasClean) { + resolve(false) + } else { + resolve(false) + } + } + }) +} + export { toHex } From 8f754ebf9ef08da5c55cc023b4acc75cc3cb23de Mon Sep 17 00:00:00 2001 From: Halil Beycan <50718965+BeycanDeveloper@users.noreply.github.com> Date: Mon, 1 Apr 2024 23:05:20 +0800 Subject: [PATCH 093/114] fixed checkWebSocket function --- packages/utils/package.json | 8 ++++++-- packages/utils/pnpm-lock.yaml | 37 +++++++++++++++++++++++++++++++++++ packages/utils/src/index.ts | 26 ++++++++++++------------ 3 files changed, 56 insertions(+), 15 deletions(-) diff --git a/packages/utils/package.json b/packages/utils/package.json index ca3c759..a92a4c9 100644 --- a/packages/utils/package.json +++ b/packages/utils/package.json @@ -1,6 +1,6 @@ { "name": "@multiplechain/utils", - "version": "0.1.11", + "version": "0.1.12", "type": "module", "main": "./src/index.ts", "types": "./src/index.ts", @@ -32,6 +32,10 @@ }, "dependencies": { "bignumber.js": "^9.1.2", - "web3-utils": "^4.2.0" + "web3-utils": "^4.2.0", + "ws": "^8.16.0" + }, + "devDependencies": { + "@types/ws": "^8.5.10" } } diff --git a/packages/utils/pnpm-lock.yaml b/packages/utils/pnpm-lock.yaml index 3ba3f9f..52ca4c5 100644 --- a/packages/utils/pnpm-lock.yaml +++ b/packages/utils/pnpm-lock.yaml @@ -11,6 +11,14 @@ dependencies: web3-utils: specifier: ^4.2.0 version: 4.2.0 + ws: + specifier: ^8.16.0 + version: 8.16.0 + +devDependencies: + '@types/ws': + specifier: ^8.5.10 + version: 8.5.10 packages: @@ -44,6 +52,18 @@ packages: '@scure/base': 1.1.5 dev: false + /@types/node@20.12.2: + resolution: {integrity: sha512-zQ0NYO87hyN6Xrclcqp7f8ZbXNbRfoGWNcMvHTPQp9UUrwI0mI7XBz+cu7/W6/VClYo2g63B0cjull/srU7LgQ==} + dependencies: + undici-types: 5.26.5 + dev: true + + /@types/ws@8.5.10: + resolution: {integrity: sha512-vmQSUcfalpIq0R9q7uTo2lXs6eGIpt9wtnLdMv9LVpIjCA/+ufZRozlVoVelIYixx1ugCBKDhn89vnsEGOCx9A==} + dependencies: + '@types/node': 20.12.2 + dev: true + /available-typed-arrays@1.0.7: resolution: {integrity: sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==} engines: {node: '>= 0.4'} @@ -201,6 +221,10 @@ packages: has-property-descriptors: 1.0.2 dev: false + /undici-types@5.26.5: + resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==} + dev: true + /util@0.12.5: resolution: {integrity: sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA==} dependencies: @@ -255,6 +279,19 @@ packages: has-tostringtag: 1.0.2 dev: false + /ws@8.16.0: + resolution: {integrity: sha512-HS0c//TP7Ina87TfiPUz1rQzMhHrl/SG2guqRcTOIUYD2q8uhUdNHZYJUaQ8aTGPzCh+c6oawMKW35nFl1dxyQ==} + engines: {node: '>=10.0.0'} + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: '>=5.0.2' + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + dev: false + /zod@3.22.4: resolution: {integrity: sha512-iC+8Io04lddc+mVqQ9AZ7OQ2MrUKGN+oIQyq1vemgt46jwCwLfhq7/pwnBnNXXXZb8VTVLKwp9EDkx+ryxIWmg==} dev: false diff --git a/packages/utils/src/index.ts b/packages/utils/src/index.ts index 0cf34d5..37fb1e1 100644 --- a/packages/utils/src/index.ts +++ b/packages/utils/src/index.ts @@ -1,5 +1,6 @@ import { toHex } from 'web3-utils' import BigNumber from 'bignumber.js' +import { WebSocket as NodeWebSocket } from 'ws' const BASE58_ALPHABET: string = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz' @@ -141,24 +142,23 @@ export const objectsEqual = (o1: any, o2: any): boolean => { * @returns {Promise} */ export const checkWebSocket = async (url: string): Promise => { - return await new Promise((resolve, reject) => { - const socket = new WebSocket(url) + return await new Promise((resolve) => { + let socket - socket.onopen = function () { - socket.close() - resolve(true) + if (typeof window !== 'undefined') { + socket = new WebSocket(url) + } else { + socket = new NodeWebSocket(url) } - socket.onerror = function () { - reject(false) // eslint-disable-line + socket.onopen = () => { + resolve(true) + socket.close() } - socket.onclose = function (event) { - if (event.wasClean) { - resolve(false) - } else { - resolve(false) - } + socket.onerror = () => { + resolve(false) + socket.close() } }) } From 62a934ff954b3deeb94c9976f1f30b4291f61658 Mon Sep 17 00:00:00 2001 From: Halil Beycan <50718965+BeycanDeveloper@users.noreply.github.com> Date: Mon, 1 Apr 2024 23:07:32 +0800 Subject: [PATCH 094/114] types added for dependencies --- packages/utils/package-lock.json | 483 +++++++++++++++++++++++++++++++ packages/utils/package.json | 6 +- 2 files changed, 485 insertions(+), 4 deletions(-) create mode 100644 packages/utils/package-lock.json diff --git a/packages/utils/package-lock.json b/packages/utils/package-lock.json new file mode 100644 index 0000000..7c5a1fe --- /dev/null +++ b/packages/utils/package-lock.json @@ -0,0 +1,483 @@ +{ + "name": "@multiplechain/utils", + "version": "0.1.13", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "@multiplechain/utils", + "version": "0.1.13", + "license": "MIT", + "dependencies": { + "@types/ws": "^8.5.10", + "bignumber.js": "^9.1.2", + "web3-utils": "^4.2.0", + "ws": "^8.16.0" + } + }, + "node_modules/@noble/curves": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.3.0.tgz", + "integrity": "sha512-t01iSXPuN+Eqzb4eBX0S5oubSqXbK/xXa1Ne18Hj8f9pStxztHCE2gfboSp/dZRLSqfuLpRK2nDXDK+W9puocA==", + "dependencies": { + "@noble/hashes": "1.3.3" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@noble/hashes": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.3.tgz", + "integrity": "sha512-V7/fPHgl+jsVPXqqeOzT8egNj2iBIVt+ECeMMG8TdcnTikP3oaBtUVqpT/gYCR68aEBJSF+XbYUxStjbFMqIIA==", + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@scure/base": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/@scure/base/-/base-1.1.6.tgz", + "integrity": "sha512-ok9AWwhcgYuGG3Zfhyqg+zwl+Wn5uE+dwC0NV/2qQkx4dABbb/bx96vWu8NSj+BNjjSjno+JRYRjle1jV08k3g==", + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@scure/bip32": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@scure/bip32/-/bip32-1.3.3.tgz", + "integrity": "sha512-LJaN3HwRbfQK0X1xFSi0Q9amqOgzQnnDngIt+ZlsBC3Bm7/nE7K0kwshZHyaru79yIVRv/e1mQAjZyuZG6jOFQ==", + "dependencies": { + "@noble/curves": "~1.3.0", + "@noble/hashes": "~1.3.2", + "@scure/base": "~1.1.4" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@scure/bip39": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@scure/bip39/-/bip39-1.2.2.tgz", + "integrity": "sha512-HYf9TUXG80beW+hGAt3TRM8wU6pQoYur9iNypTROm42dorCGmLnFe3eWjz3gOq6G62H2WRh0FCzAR1PI+29zIA==", + "dependencies": { + "@noble/hashes": "~1.3.2", + "@scure/base": "~1.1.4" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@types/node": { + "version": "20.12.2", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.12.2.tgz", + "integrity": "sha512-zQ0NYO87hyN6Xrclcqp7f8ZbXNbRfoGWNcMvHTPQp9UUrwI0mI7XBz+cu7/W6/VClYo2g63B0cjull/srU7LgQ==", + "dependencies": { + "undici-types": "~5.26.4" + } + }, + "node_modules/@types/ws": { + "version": "8.5.10", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.10.tgz", + "integrity": "sha512-vmQSUcfalpIq0R9q7uTo2lXs6eGIpt9wtnLdMv9LVpIjCA/+ufZRozlVoVelIYixx1ugCBKDhn89vnsEGOCx9A==", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/available-typed-arrays": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", + "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", + "dependencies": { + "possible-typed-array-names": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/bignumber.js": { + "version": "9.1.2", + "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.1.2.tgz", + "integrity": "sha512-2/mKyZH9K85bzOEfhXDBFZTGd1CTs+5IHpeFQo9luiBG7hghdC851Pj2WAhb6E3R6b9tZj/XKhbg4fum+Kepug==", + "engines": { + "node": "*" + } + }, + "node_modules/call-bind": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", + "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "set-function-length": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/define-data-property": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/es-define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", + "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", + "dependencies": { + "get-intrinsic": "^1.2.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/ethereum-cryptography": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-2.1.3.tgz", + "integrity": "sha512-BlwbIL7/P45W8FGW2r7LGuvoEZ+7PWsniMvQ4p5s2xCyw9tmaDlpfsN9HjAucbF+t/qpVHwZUisgfK24TCW8aA==", + "dependencies": { + "@noble/curves": "1.3.0", + "@noble/hashes": "1.3.3", + "@scure/bip32": "1.3.3", + "@scure/bip39": "1.2.2" + } + }, + "node_modules/eventemitter3": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz", + "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==" + }, + "node_modules/for-each": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", + "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", + "dependencies": { + "is-callable": "^1.1.3" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-intrinsic": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", + "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "hasown": "^2.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/gopd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", + "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", + "dependencies": { + "get-intrinsic": "^1.1.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-property-descriptors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", + "dependencies": { + "es-define-property": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-proto": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", + "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "dependencies": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "node_modules/is-arguments": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz", + "integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==", + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-callable": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", + "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-generator-function": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz", + "integrity": "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==", + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-typed-array": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.13.tgz", + "integrity": "sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw==", + "dependencies": { + "which-typed-array": "^1.1.14" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/possible-typed-array-names": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz", + "integrity": "sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/set-function-length": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", + "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/undici-types": { + "version": "5.26.5", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==" + }, + "node_modules/util": { + "version": "0.12.5", + "resolved": "https://registry.npmjs.org/util/-/util-0.12.5.tgz", + "integrity": "sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA==", + "dependencies": { + "inherits": "^2.0.3", + "is-arguments": "^1.0.4", + "is-generator-function": "^1.0.7", + "is-typed-array": "^1.1.3", + "which-typed-array": "^1.1.2" + } + }, + "node_modules/web3-errors": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/web3-errors/-/web3-errors-1.1.4.tgz", + "integrity": "sha512-WahtszSqILez+83AxGecVroyZsMuuRT+KmQp4Si5P4Rnqbczno1k748PCrZTS1J4UCPmXMG2/Vt+0Bz2zwXkwQ==", + "dependencies": { + "web3-types": "^1.3.1" + }, + "engines": { + "node": ">=14", + "npm": ">=6.12.0" + } + }, + "node_modules/web3-types": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/web3-types/-/web3-types-1.5.0.tgz", + "integrity": "sha512-geWuMIeegQ8AedKAO6wO4G4j1gyQ1F/AyKLMw2vud4bsfZayyzWJgCMDZtjYMm5uo2a7i8j1W3/4QFmzlSy5cw==", + "engines": { + "node": ">=14", + "npm": ">=6.12.0" + } + }, + "node_modules/web3-utils": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-4.2.2.tgz", + "integrity": "sha512-z+4owWcnoB4EH8yWIL1FBeyqe+sXwaGxUDtVTNPTMf2oB5C+paCToZUdCV5Bi+M543zZEzlzNTabOD+OWNc7NA==", + "dependencies": { + "ethereum-cryptography": "^2.0.0", + "eventemitter3": "^5.0.1", + "web3-errors": "^1.1.4", + "web3-types": "^1.5.0", + "web3-validator": "^2.0.5" + }, + "engines": { + "node": ">=14", + "npm": ">=6.12.0" + } + }, + "node_modules/web3-validator": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/web3-validator/-/web3-validator-2.0.5.tgz", + "integrity": "sha512-2gLOSW8XqEN5pw5jVUm20EB7A8SbQiekpAtiI0JBmCIV0a2rp97v8FgWY5E3UEqnw5WFfEqvcDVW92EyynDTyQ==", + "dependencies": { + "ethereum-cryptography": "^2.0.0", + "util": "^0.12.5", + "web3-errors": "^1.1.4", + "web3-types": "^1.5.0", + "zod": "^3.21.4" + }, + "engines": { + "node": ">=14", + "npm": ">=6.12.0" + } + }, + "node_modules/which-typed-array": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.15.tgz", + "integrity": "sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA==", + "dependencies": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/ws": { + "version": "8.16.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.16.0.tgz", + "integrity": "sha512-HS0c//TP7Ina87TfiPUz1rQzMhHrl/SG2guqRcTOIUYD2q8uhUdNHZYJUaQ8aTGPzCh+c6oawMKW35nFl1dxyQ==", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/zod": { + "version": "3.22.4", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.22.4.tgz", + "integrity": "sha512-iC+8Io04lddc+mVqQ9AZ7OQ2MrUKGN+oIQyq1vemgt46jwCwLfhq7/pwnBnNXXXZb8VTVLKwp9EDkx+ryxIWmg==", + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } + } + } +} diff --git a/packages/utils/package.json b/packages/utils/package.json index a92a4c9..9b68b5a 100644 --- a/packages/utils/package.json +++ b/packages/utils/package.json @@ -1,6 +1,6 @@ { "name": "@multiplechain/utils", - "version": "0.1.12", + "version": "0.1.13", "type": "module", "main": "./src/index.ts", "types": "./src/index.ts", @@ -33,9 +33,7 @@ "dependencies": { "bignumber.js": "^9.1.2", "web3-utils": "^4.2.0", - "ws": "^8.16.0" - }, - "devDependencies": { + "ws": "^8.16.0", "@types/ws": "^8.5.10" } } From f8f2f25ce546e43216b0d186c04ace4b66c9d050 Mon Sep 17 00:00:00 2001 From: Halil Beycan <50718965+BeycanDeveloper@users.noreply.github.com> Date: Mon, 1 Apr 2024 23:09:20 +0800 Subject: [PATCH 095/114] fixed socket type problem --- packages/utils/package.json | 2 +- packages/utils/src/index.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/utils/package.json b/packages/utils/package.json index 9b68b5a..9b40b5f 100644 --- a/packages/utils/package.json +++ b/packages/utils/package.json @@ -1,6 +1,6 @@ { "name": "@multiplechain/utils", - "version": "0.1.13", + "version": "0.1.14", "type": "module", "main": "./src/index.ts", "types": "./src/index.ts", diff --git a/packages/utils/src/index.ts b/packages/utils/src/index.ts index 37fb1e1..3df0e8a 100644 --- a/packages/utils/src/index.ts +++ b/packages/utils/src/index.ts @@ -143,7 +143,7 @@ export const objectsEqual = (o1: any, o2: any): boolean => { */ export const checkWebSocket = async (url: string): Promise => { return await new Promise((resolve) => { - let socket + let socket: WebSocket | NodeWebSocket if (typeof window !== 'undefined') { socket = new WebSocket(url) From f7462d39403175d05aee4fdd06edade5656e955a Mon Sep 17 00:00:00 2001 From: Halil Beycan <50718965+BeycanDeveloper@users.noreply.github.com> Date: Mon, 1 Apr 2024 23:26:38 +0800 Subject: [PATCH 096/114] ready for all platforms --- .gitignore | 1 + esbuild.ts | 19 ++++++ package.json | 1 + packages/networks/boilerplate/esbuild.ts | 3 + packages/networks/boilerplate/package.json | 11 ++-- packages/networks/evm-chains/esbuild.ts | 3 + packages/networks/evm-chains/package.json | 16 ++--- packages/networks/evm-chains/pnpm-lock.yaml | 44 +++++++++++-- packages/networks/evm-chains/src/index.ts | 7 ++ .../evm-chains/src/services/Networks.ts | 65 +++++++++++++++++++ pnpm-lock.yaml | 14 ++++ tsconfig.json | 9 ++- vite.config.ts | 1 + 13 files changed, 175 insertions(+), 19 deletions(-) create mode 100644 esbuild.ts create mode 100644 packages/networks/boilerplate/esbuild.ts create mode 100644 packages/networks/evm-chains/esbuild.ts create mode 100644 packages/networks/evm-chains/src/services/Networks.ts diff --git a/.gitignore b/.gitignore index fa2a173..6bc6b68 100644 --- a/.gitignore +++ b/.gitignore @@ -15,6 +15,7 @@ dist-ssr index.html test*.ts test*.js +test*.cjs # Editor directories and files .vscode/* diff --git a/esbuild.ts b/esbuild.ts new file mode 100644 index 0000000..6357475 --- /dev/null +++ b/esbuild.ts @@ -0,0 +1,19 @@ +import { build, type BuildOptions } from 'esbuild' + +const baseConfig: BuildOptions = { + entryPoints: ['src/index.ts'], + bundle: true, + platform: 'node', + format: 'cjs', + minify: true, + sourcemap: true, + logLevel: 'info', + outfile: 'dist/index.cjs' +} + +export default (customConfig: BuildOptions = {}): void => { + build({ + ...baseConfig, + ...customConfig + }).catch(() => process.exit(1)) +} diff --git a/package.json b/package.json index 204ec27..a841273 100644 --- a/package.json +++ b/package.json @@ -26,6 +26,7 @@ "eslint-plugin-require-extensions": "^0.1.3", "jsdom": "^24.0.0", "prettier": "^3.2.5", + "tsx": "^4.7.1", "typescript": "^5.3.3", "vite": "^5.1.4", "vite-plugin-dts": "^3.8.1", diff --git a/packages/networks/boilerplate/esbuild.ts b/packages/networks/boilerplate/esbuild.ts new file mode 100644 index 0000000..5714b9c --- /dev/null +++ b/packages/networks/boilerplate/esbuild.ts @@ -0,0 +1,3 @@ +void import('../../../esbuild.ts').then((module) => { + module.default() +}) diff --git a/packages/networks/boilerplate/package.json b/packages/networks/boilerplate/package.json index 5d9b6a7..5d302a6 100644 --- a/packages/networks/boilerplate/package.json +++ b/packages/networks/boilerplate/package.json @@ -1,8 +1,9 @@ { "name": "@multiplechain/evm-chains", "version": "0.1.0", + "type": "module", "types": "dist/index.d.ts", - "main": "dist/index.cjs.js", + "main": "dist/index.cjs", "module": "dist/index.es.js", "unpkg": "dist/index.umd.js", "browser": "dist/index.umd.js", @@ -10,7 +11,7 @@ "exports": { ".": { "import": "./dist/index.es.js", - "require": "./dist/index.cjs.js" + "require": "./dist/index.cjs" } }, "files": [ @@ -22,12 +23,12 @@ "clean": "rm -rf dist", "watch": "tsc --watch", "build:vite": "vite build", + "build:node": "tsx esbuild.ts", "typecheck": "tsc --noEmit", "lint": "eslint . --ext .ts", "test": "vitest run --dir tests", "prepublishOnly": "pnpm run build", - "build": "pnpm run build:vite && pnpm run build:node", - "build:node": "esbuild src/index.ts --bundle --platform=node --format=cjs --outfile=dist/index.cjs.js" + "build": "pnpm run build:vite && pnpm run build:node" }, "keywords": [ "web3", @@ -47,6 +48,6 @@ }, "dependencies": { "@multiplechain/types": "^0.1.30", - "@multiplechain/utils": "^0.1.10" + "@multiplechain/utils": "^0.1.14" } } \ No newline at end of file diff --git a/packages/networks/evm-chains/esbuild.ts b/packages/networks/evm-chains/esbuild.ts new file mode 100644 index 0000000..5714b9c --- /dev/null +++ b/packages/networks/evm-chains/esbuild.ts @@ -0,0 +1,3 @@ +void import('../../../esbuild.ts').then((module) => { + module.default() +}) diff --git a/packages/networks/evm-chains/package.json b/packages/networks/evm-chains/package.json index 2976f8d..edfaa3e 100644 --- a/packages/networks/evm-chains/package.json +++ b/packages/networks/evm-chains/package.json @@ -1,9 +1,9 @@ { "name": "@multiplechain/evm-chains", - "version": "0.3.34", + "version": "0.3.35", "type": "module", "types": "dist/index.d.ts", - "main": "dist/index.cjs.js", + "main": "dist/index.cjs", "module": "dist/index.es.js", "unpkg": "dist/index.umd.js", "browser": "dist/index.umd.js", @@ -11,7 +11,7 @@ "exports": { ".": { "import": "./dist/index.es.js", - "require": "./dist/index.cjs.js" + "require": "./dist/index.cjs" } }, "files": [ @@ -23,12 +23,12 @@ "clean": "rm -rf dist", "watch": "tsc --watch", "build:vite": "vite build", + "build:node": "tsx esbuild.ts", "typecheck": "tsc --noEmit", "lint": "eslint . --ext .ts", "test": "vitest run --dir tests", "prepublishOnly": "pnpm run build", - "build": "pnpm run build:vite && pnpm run build:node", - "build:node": "esbuild src/index.ts --bundle --platform=node --format=cjs --outfile=dist/index.cjs.js" + "build": "pnpm run build:vite && pnpm run build:node" }, "keywords": [ "web3", @@ -51,10 +51,8 @@ }, "dependencies": { "@multiplechain/types": "^0.1.30", - "@multiplechain/utils": "^0.1.10", + "@multiplechain/utils": "^0.1.14", + "@wagmi/chains": "^1.8.0", "ethers": "^6.11.1" - }, - "devDependencies": { - "esbuild": "^0.20.2" } } \ No newline at end of file diff --git a/packages/networks/evm-chains/pnpm-lock.yaml b/packages/networks/evm-chains/pnpm-lock.yaml index f01cc5b..662fb8e 100644 --- a/packages/networks/evm-chains/pnpm-lock.yaml +++ b/packages/networks/evm-chains/pnpm-lock.yaml @@ -9,8 +9,11 @@ dependencies: specifier: ^0.1.30 version: 0.1.30 '@multiplechain/utils': - specifier: ^0.1.10 - version: 0.1.10 + specifier: ^0.1.14 + version: 0.1.14 + '@wagmi/chains': + specifier: ^1.8.0 + version: 1.8.0 ethers: specifier: ^6.11.1 version: 6.11.1 @@ -25,11 +28,16 @@ packages: resolution: {integrity: sha512-j72Ydn1FlEWF4lY6xUjI0ojf0y1JAjqYnddAaUUdzv5sRlFw2zze8VLqxzltFtjFigPbSUa7QHmbgTIXQ60HoQ==} dev: false - /@multiplechain/utils@0.1.10: - resolution: {integrity: sha512-Ed0YxvRakds1WiREcLWI+fr6YCNB3bSORPD/ZQNqhELtL5uVgYWunIwbx6yZmLNk4MY8Qqyh0iUjuCOBLplmiA==} + /@multiplechain/utils@0.1.14: + resolution: {integrity: sha512-MfpnKq8FHW0GgwSEeV3HprBUrJiCXW7PC3Ei1s3ii8wsWd46KC62a1+5fCuYk3fteupquxYYl72HhKhgbmczSA==} dependencies: + '@types/ws': 8.5.10 bignumber.js: 9.1.2 web3-utils: 4.2.2 + ws: 8.16.0 + transitivePeerDependencies: + - bufferutil + - utf-8-validate dev: false /@noble/curves@1.2.0: @@ -77,6 +85,21 @@ packages: resolution: {integrity: sha512-N+0kuo9KgrUQ1Sn/ifDXsvg0TTleP7rIy4zOBGECxAljqvqfqpTfzx0Q1NUedOixRMBfe2Whhb056a42cWs26Q==} dev: false + /@types/ws@8.5.10: + resolution: {integrity: sha512-vmQSUcfalpIq0R9q7uTo2lXs6eGIpt9wtnLdMv9LVpIjCA/+ufZRozlVoVelIYixx1ugCBKDhn89vnsEGOCx9A==} + dependencies: + '@types/node': 18.15.13 + dev: false + + /@wagmi/chains@1.8.0: + resolution: {integrity: sha512-UXo0GF0Cl0+neKC2KAmVAahv8L/5rACbFRRqkDvHMefzY6Fh7yzJd8F4GaGNNG3w4hj8eUB/E3+dEpaTYDN62w==} + peerDependencies: + typescript: '>=5.0.4' + peerDependenciesMeta: + typescript: + optional: true + dev: false + /aes-js@4.0.0-beta.5: resolution: {integrity: sha512-G965FqalsNyrPqgEGON7nIx1e/OVENSgiEIzyC63haUMuvNnwIgIjMs52hlTCKhkBny7A2ORNlfY9Zu+jmGk1Q==} dev: false @@ -317,6 +340,19 @@ packages: has-tostringtag: 1.0.2 dev: false + /ws@8.16.0: + resolution: {integrity: sha512-HS0c//TP7Ina87TfiPUz1rQzMhHrl/SG2guqRcTOIUYD2q8uhUdNHZYJUaQ8aTGPzCh+c6oawMKW35nFl1dxyQ==} + engines: {node: '>=10.0.0'} + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: '>=5.0.2' + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + dev: false + /ws@8.5.0: resolution: {integrity: sha512-BWX0SWVgLPzYwF8lTzEy1egjhS4S4OEAHfsO8o65WOVsrnSRGaSiUaa9e0ggGlkMTtBlmOpEXiie9RUcBO86qg==} engines: {node: '>=10.0.0'} diff --git a/packages/networks/evm-chains/src/index.ts b/packages/networks/evm-chains/src/index.ts index 668ab52..9c367a9 100644 --- a/packages/networks/evm-chains/src/index.ts +++ b/packages/networks/evm-chains/src/index.ts @@ -1,3 +1,5 @@ +import allNetworks, * as methods from './services/Networks.ts' + export * from './services/Provider.ts' export * as assets from './assets/index.ts' @@ -6,3 +8,8 @@ export * as services from './services/index.ts' export * as utils from '@multiplechain/utils' export * as types from '@multiplechain/types' + +export const networks = { + ...methods, + ...allNetworks +} diff --git a/packages/networks/evm-chains/src/services/Networks.ts b/packages/networks/evm-chains/src/services/Networks.ts new file mode 100644 index 0000000..ac3a6cc --- /dev/null +++ b/packages/networks/evm-chains/src/services/Networks.ts @@ -0,0 +1,65 @@ +import * as wagmiChains from '@wagmi/chains' +import type { EvmNetworkConfigInterface } from './Provider.ts' + +const networks: Record = {} + +Object.keys(wagmiChains).forEach((key) => { + const wagmiChain: wagmiChains.Chain = wagmiChains[key as keyof typeof wagmiChains] + + let backupRpcUrl = '' + if (wagmiChain.rpcUrls?.infura !== undefined) { + backupRpcUrl = wagmiChain.rpcUrls.infura.http[0] + } else if (wagmiChain.rpcUrls?.alchemy !== undefined) { + backupRpcUrl = wagmiChain.rpcUrls.alchemy.http[0] + } + + const network: EvmNetworkConfigInterface = { + id: wagmiChain.id, + name: wagmiChain.name, + testnet: wagmiChain.testnet ?? false, + nativeCurrency: wagmiChain.nativeCurrency, + hexId: '0x' + Number(wagmiChain.id).toString(16), + explorerUrl: wagmiChain.blockExplorers?.default.url ?? '', + rpcUrl: wagmiChain.rpcUrls?.default.http[0] ?? backupRpcUrl + } + + if (wagmiChain.rpcUrls?.default.webSocket !== undefined) { + network.wsUrl = wagmiChain.rpcUrls.default.webSocket[0] + } + + if (wagmiChain.rpcUrls?.infura?.webSocket !== undefined && network.wsUrl === undefined) { + network.wsUrl = wagmiChain.rpcUrls.infura.webSocket[0] + } + + if (wagmiChain.rpcUrls?.alchemy?.webSocket !== undefined && network.wsUrl === undefined) { + network.wsUrl = wagmiChain.rpcUrls.alchemy.webSocket[0] + } + + if (network.wsUrl === undefined) { + delete network.wsUrl + } + + networks[key === 'mainnet' ? 'ethereum' : key] = network +}) + +export const findByKey = (key: string): EvmNetworkConfigInterface | undefined => { + return networks[key] +} + +export const findByName = (name: string): EvmNetworkConfigInterface | undefined => { + return Object.values(networks).find((network) => network.name?.includes(name)) +} + +export const findById = (id: number): EvmNetworkConfigInterface | undefined => { + return Object.values(networks).find((network) => network.id === id) +} + +export const findByHexId = (hexId: string): EvmNetworkConfigInterface | undefined => { + return Object.values(networks).find((network) => network.hexId === hexId) +} + +export const findBySymbol = (symbol: string): EvmNetworkConfigInterface | undefined => { + return Object.values(networks).find((network) => network.nativeCurrency.symbol === symbol) +} + +export default networks diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 807f5d2..4d5006e 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -47,6 +47,9 @@ devDependencies: prettier: specifier: ^3.2.5 version: 3.2.5 + tsx: + specifier: ^4.7.1 + version: 4.7.1 typescript: specifier: ^5.3.3 version: 5.3.3 @@ -3813,6 +3816,17 @@ packages: resolution: {integrity: sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==} dev: true + /tsx@4.7.1: + resolution: {integrity: sha512-8d6VuibXHtlN5E3zFkgY8u4DX7Y3Z27zvvPKVmLon/D4AjuKzarkUBTLDBgj9iTQ0hg5xM7c/mYiRVM+HETf0g==} + engines: {node: '>=18.0.0'} + hasBin: true + dependencies: + esbuild: 0.19.12 + get-tsconfig: 4.7.2 + optionalDependencies: + fsevents: 2.3.3 + dev: true + /tty-browserify@0.0.1: resolution: {integrity: sha512-C3TaO7K81YvjCgQH9Q1S3R3P3BtN3RIM8n+OvX4il1K1zgE8ZhI0op7kClgkxtutIE8hQrcrHBXvIheqKUUCxw==} dev: true diff --git a/tsconfig.json b/tsconfig.json index 492dc24..08215d8 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -22,6 +22,13 @@ "noFallthroughCasesInSwitch": true, "strictPropertyInitialization": false }, - "include": ["packages/**/*.ts", ".eslintrc.json", "vite.config.ts", "vitest.config.ts", "vite-env.d.ts"], + "include": [ + "packages/**/*.ts", + ".eslintrc.json", + "vite.config.ts", + "vitest.config.ts", + "vite-env.d.ts", + "esbuild.ts" + ], "exclude": ["node_modules", "dist", "packages/**/*.d.ts"] } diff --git a/vite.config.ts b/vite.config.ts index eb11468..a20fb22 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -8,6 +8,7 @@ export default defineConfig({ }) ], build: { + minify: true, sourcemap: true, lib: { entry: './src/index.ts', From 3bf0116a4a85578564d35025f8b44373c20f03a5 Mon Sep 17 00:00:00 2001 From: Halil Beycan <50718965+BeycanDeveloper@users.noreply.github.com> Date: Tue, 2 Apr 2024 00:07:39 +0800 Subject: [PATCH 097/114] Prevented Ethers websocket process from breaking the whole application --- packages/networks/evm-chains/package.json | 2 +- .../evm-chains/src/services/Ethers.ts | 27 ++++++++++++++++--- .../src/services/TransactionListener.ts | 19 ++++++++----- 3 files changed, 36 insertions(+), 12 deletions(-) diff --git a/packages/networks/evm-chains/package.json b/packages/networks/evm-chains/package.json index edfaa3e..7b158c3 100644 --- a/packages/networks/evm-chains/package.json +++ b/packages/networks/evm-chains/package.json @@ -1,6 +1,6 @@ { "name": "@multiplechain/evm-chains", - "version": "0.3.35", + "version": "0.3.36", "type": "module", "types": "dist/index.d.ts", "main": "dist/index.cjs", diff --git a/packages/networks/evm-chains/src/services/Ethers.ts b/packages/networks/evm-chains/src/services/Ethers.ts index 68f1cce..73c82f2 100644 --- a/packages/networks/evm-chains/src/services/Ethers.ts +++ b/packages/networks/evm-chains/src/services/Ethers.ts @@ -7,7 +7,7 @@ import type { TransactionReceipt, TransactionResponse } from 'ethers' -import { sleep } from '@multiplechain/utils' +import { sleep, checkWebSocket } from '@multiplechain/utils' import type { EvmNetworkConfigInterface } from './Provider.ts' import type { TransactionData } from '../services/TransactionSigner.ts' import { Wallet, Contract, ContractFactory, JsonRpcProvider, WebSocketProvider } from 'ethers' @@ -36,9 +36,6 @@ export class Ethers { constructor(network: EvmNetworkConfigInterface) { this.network = network this.jsonRpcProvider = new JsonRpcProvider(network.rpcUrl) - if (network.wsUrl !== undefined) { - this.webSocketProvider = new WebSocketProvider(network.wsUrl) - } } /** @@ -55,6 +52,28 @@ export class Ethers { return this.webSocketProvider } + /** + * @returns {WebSocketProvider | undefined} + */ + public async connectWebSocket(): Promise { + return await new Promise((resolve, reject) => { + if (this.network.wsUrl === undefined) { + resolve(undefined) + } else { + const url = this.network.wsUrl + checkWebSocket(url) + .then((status) => { + if (status) { + resolve((this.webSocketProvider = new WebSocketProvider(url))) + } else { + resolve(undefined) + } + }) + .catch(reject) + } + }) + } + /** * @param {String} address * @param {InterfaceAbi} abi diff --git a/packages/networks/evm-chains/src/services/TransactionListener.ts b/packages/networks/evm-chains/src/services/TransactionListener.ts index 5b3f7d6..27130f8 100644 --- a/packages/networks/evm-chains/src/services/TransactionListener.ts +++ b/packages/networks/evm-chains/src/services/TransactionListener.ts @@ -82,12 +82,6 @@ export class TransactionListener this.provider = provider ?? Provider.instance this.ethers = this.provider.ethers this.jsonRpc = this.provider.ethers.jsonRpc - // Check if the WebSocket URL is defined - if (this.provider.ethers.webSocket === undefined) { - throw new Error('WebSocket URL is not defined') - } else { - this.webSocket = this.provider.ethers.webSocket - } } /** @@ -126,9 +120,20 @@ export class TransactionListener * @param {TransactionListenerCallbackType} callback - Callback function * @returns {void} */ - on(callback: TransactionListenerCallbackType): void { + async on(callback: TransactionListenerCallbackType): Promise { + if (this.webSocket === undefined) { + const socket = await this.provider.ethers.connectWebSocket() + if (socket === undefined) { + throw new Error('WebSocket connection is not available') + } else { + this.webSocket = socket + } + } + this.start() this.callbacks.push(callback) + + return true } /** From 6b3a03eaf9f4822124a426448650401c05bf87e4 Mon Sep 17 00:00:00 2001 From: Halil Beycan <50718965+BeycanDeveloper@users.noreply.github.com> Date: Tue, 2 Apr 2024 01:08:57 +0800 Subject: [PATCH 098/114] optimized for listen by address --- .../src/services/TransactionListener.ts | 52 +++++++++++++------ 1 file changed, 35 insertions(+), 17 deletions(-) diff --git a/packages/networks/evm-chains/src/services/TransactionListener.ts b/packages/networks/evm-chains/src/services/TransactionListener.ts index 27130f8..1e4f432 100644 --- a/packages/networks/evm-chains/src/services/TransactionListener.ts +++ b/packages/networks/evm-chains/src/services/TransactionListener.ts @@ -16,10 +16,16 @@ import { CoinTransaction } from '../models/CoinTransaction.ts' import { TokenTransaction } from '../models/TokenTransaction.ts' import { TransactionListenerProcessIndex } from '@multiplechain/types' import { ContractTransaction } from '../models/ContractTransaction.ts' -import type { WebSocketProvider, JsonRpcApiProvider, EventFilter, Log } from 'ethers' +import type { + WebSocketProvider, + JsonRpcApiProvider, + EventFilter, + Log, + TransactionResponse +} from 'ethers' export class TransactionListener - implements TransactionListenerInterface + implements Omit, 'filter'> { /** * Transaction type @@ -34,7 +40,7 @@ export class TransactionListener /** * Transaction listener filter */ - filter?: DynamicTransactionListenerFilterType + filter?: DynamicTransactionListenerFilterType | Record /** * Provider @@ -78,7 +84,7 @@ export class TransactionListener */ constructor(type: T, provider?: Provider, filter?: DynamicTransactionListenerFilterType) { this.type = type - this.filter = filter + this.filter = filter ?? {} this.provider = provider ?? Provider.instance this.ethers = this.provider.ethers this.jsonRpc = this.provider.ethers.jsonRpc @@ -180,27 +186,39 @@ export class TransactionListener const filter = this .filter as DynamicTransactionListenerFilterType - const callback = async (transactionId: string): Promise => { - const transaction = await this.ethers.getTransaction(transactionId) - const contractBytecode = await this.ethers.getByteCode(transaction?.to ?? '') + let params: string | EventFilter + if (filter.address === undefined) { + params = 'pending' + } else { + params = { + address: filter.address + } + } + + const callback = async (transactionIdOrLog: string | Log): Promise => { + let transaction: TransactionResponse | null + if (typeof transactionIdOrLog === 'string') { + transaction = await this.ethers.getTransaction(transactionIdOrLog) + const contractBytecode = await this.ethers.getByteCode(transaction?.to ?? '') + + if (contractBytecode === '0x') { + return + } + } else { + transaction = await this.ethers.getTransaction(transactionIdOrLog.transactionHash) + } - if (contractBytecode === '0x' || transaction === null) { + if (transaction === null) { return } interface ParamsType { - address?: string signer?: string } const expectedParams: ParamsType = {} const receivedParams: ParamsType = {} - if (filter.address !== undefined) { - expectedParams.address = filter.address.toLowerCase() - receivedParams.address = transaction.to?.toLowerCase() - } - if (filter.signer !== undefined) { expectedParams.signer = filter.signer.toLowerCase() receivedParams.signer = transaction.from.toLowerCase() @@ -210,12 +228,12 @@ export class TransactionListener return } - this.trigger(new ContractTransaction(transactionId)) + this.trigger(new ContractTransaction(transaction.hash)) } - void this.webSocket.on('pending', callback) + void this.webSocket.on(params, callback) this.dynamicStop = () => { - void this.webSocket.off('pending', callback) + void this.webSocket.off(params, callback) } } From ab658e5bdf052b0f3b9040a29c5896bf2a1ce8b5 Mon Sep 17 00:00:00 2001 From: Halil Beycan <50718965+BeycanDeveloper@users.noreply.github.com> Date: Fri, 5 Apr 2024 16:32:56 +0800 Subject: [PATCH 099/114] updated --- packages/utils/package.json | 2 +- packages/utils/src/index.ts | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/packages/utils/package.json b/packages/utils/package.json index 9b40b5f..4a9d526 100644 --- a/packages/utils/package.json +++ b/packages/utils/package.json @@ -1,6 +1,6 @@ { "name": "@multiplechain/utils", - "version": "0.1.14", + "version": "0.1.15", "type": "module", "main": "./src/index.ts", "types": "./src/index.ts", diff --git a/packages/utils/src/index.ts b/packages/utils/src/index.ts index 3df0e8a..bc48034 100644 --- a/packages/utils/src/index.ts +++ b/packages/utils/src/index.ts @@ -1,6 +1,6 @@ import { toHex } from 'web3-utils' import BigNumber from 'bignumber.js' -import { WebSocket as NodeWebSocket } from 'ws' +import { WebSocket as NodeWebSocket, type ErrorEvent } from 'ws' const BASE58_ALPHABET: string = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz' @@ -139,10 +139,10 @@ export const objectsEqual = (o1: any, o2: any): boolean => { /** * checks if the given url is a valid websocket url * @param {string} url - * @returns {Promise} + * @returns {Promise} */ -export const checkWebSocket = async (url: string): Promise => { - return await new Promise((resolve) => { +export const checkWebSocket = async (url: string): Promise => { + return await new Promise((resolve, reject) => { let socket: WebSocket | NodeWebSocket if (typeof window !== 'undefined') { @@ -156,8 +156,8 @@ export const checkWebSocket = async (url: string): Promise => { socket.close() } - socket.onerror = () => { - resolve(false) + socket.onerror = (error: ErrorEvent) => { + reject(error.message) socket.close() } }) From 04bf3cf70c635414a53247ce69897300a253b5e9 Mon Sep 17 00:00:00 2001 From: Halil Beycan <50718965+BeycanDeveloper@users.noreply.github.com> Date: Fri, 5 Apr 2024 16:37:36 +0800 Subject: [PATCH 100/114] updated --- packages/utils/package.json | 4 ++-- packages/utils/pnpm-lock.yaml | 14 ++++++-------- 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/packages/utils/package.json b/packages/utils/package.json index 4a9d526..65cd08d 100644 --- a/packages/utils/package.json +++ b/packages/utils/package.json @@ -31,9 +31,9 @@ "url": "https://github.com/MultipleChain/js/issues" }, "dependencies": { + "@types/ws": "^8.5.10", "bignumber.js": "^9.1.2", "web3-utils": "^4.2.0", - "ws": "^8.16.0", - "@types/ws": "^8.5.10" + "ws": "^8.16.0" } } diff --git a/packages/utils/pnpm-lock.yaml b/packages/utils/pnpm-lock.yaml index 52ca4c5..0f511d4 100644 --- a/packages/utils/pnpm-lock.yaml +++ b/packages/utils/pnpm-lock.yaml @@ -5,6 +5,9 @@ settings: excludeLinksFromLockfile: false dependencies: + '@types/ws': + specifier: ^8.5.10 + version: 8.5.10 bignumber.js: specifier: ^9.1.2 version: 9.1.2 @@ -15,11 +18,6 @@ dependencies: specifier: ^8.16.0 version: 8.16.0 -devDependencies: - '@types/ws': - specifier: ^8.5.10 - version: 8.5.10 - packages: /@noble/curves@1.3.0: @@ -56,13 +54,13 @@ packages: resolution: {integrity: sha512-zQ0NYO87hyN6Xrclcqp7f8ZbXNbRfoGWNcMvHTPQp9UUrwI0mI7XBz+cu7/W6/VClYo2g63B0cjull/srU7LgQ==} dependencies: undici-types: 5.26.5 - dev: true + dev: false /@types/ws@8.5.10: resolution: {integrity: sha512-vmQSUcfalpIq0R9q7uTo2lXs6eGIpt9wtnLdMv9LVpIjCA/+ufZRozlVoVelIYixx1ugCBKDhn89vnsEGOCx9A==} dependencies: '@types/node': 20.12.2 - dev: true + dev: false /available-typed-arrays@1.0.7: resolution: {integrity: sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==} @@ -223,7 +221,7 @@ packages: /undici-types@5.26.5: resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==} - dev: true + dev: false /util@0.12.5: resolution: {integrity: sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA==} From 188c924832ecab3b3e461eadfd5803574256f697 Mon Sep 17 00:00:00 2001 From: Halil Beycan <50718965+BeycanDeveloper@users.noreply.github.com> Date: Fri, 5 Apr 2024 17:44:20 +0800 Subject: [PATCH 101/114] added new types --- packages/types/package.json | 2 +- packages/types/src/services/ProviderInterface.ts | 5 +++++ packages/types/src/services/TransactionListenerInterface.ts | 2 +- 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/packages/types/package.json b/packages/types/package.json index 652ff38..e9bce0e 100644 --- a/packages/types/package.json +++ b/packages/types/package.json @@ -1,6 +1,6 @@ { "name": "@multiplechain/types", - "version": "0.1.30", + "version": "0.1.31", "type": "module", "main": "./src/index.ts", "types": "./src/index.ts", diff --git a/packages/types/src/services/ProviderInterface.ts b/packages/types/src/services/ProviderInterface.ts index 231d62d..91e2ef9 100644 --- a/packages/types/src/services/ProviderInterface.ts +++ b/packages/types/src/services/ProviderInterface.ts @@ -24,4 +24,9 @@ export interface ProviderInterface { * Get the current network configuration is testnet or not */ isTestnet: () => boolean + + /** + * Check RPC connection + */ + checkConnection: (url: string) => Promise } diff --git a/packages/types/src/services/TransactionListenerInterface.ts b/packages/types/src/services/TransactionListenerInterface.ts index 8fd19cc..b3d3764 100644 --- a/packages/types/src/services/TransactionListenerInterface.ts +++ b/packages/types/src/services/TransactionListenerInterface.ts @@ -121,7 +121,7 @@ export interface TransactionListenerInterface { * 'filter' is an object that has values depending on transaction listener type. * E.g. no matter which type of transaction is listening, 'filter' has to have a 'sender' value */ - filter?: DynamicTransactionListenerFilterType + filter?: DynamicTransactionListenerFilterType | Record /** * stop() method closes the corresponding listener of the instance it's called from. From 52a1b4b2a011f702c56291fe4a9be8efebd6a39f Mon Sep 17 00:00:00 2001 From: Halil Beycan <50718965+BeycanDeveloper@users.noreply.github.com> Date: Fri, 5 Apr 2024 17:48:15 +0800 Subject: [PATCH 102/114] added rpc connection control method --- packages/networks/boilerplate/package.json | 4 +-- packages/networks/evm-chains/package.json | 4 +-- packages/networks/evm-chains/pnpm-lock.yaml | 16 +++++----- .../evm-chains/src/services/Ethers.ts | 10 +++---- .../evm-chains/src/services/Provider.ts | 30 +++++++++++++++++++ .../src/services/TransactionListener.ts | 16 +++++----- 6 files changed, 55 insertions(+), 25 deletions(-) diff --git a/packages/networks/boilerplate/package.json b/packages/networks/boilerplate/package.json index 5d302a6..e69eca7 100644 --- a/packages/networks/boilerplate/package.json +++ b/packages/networks/boilerplate/package.json @@ -47,7 +47,7 @@ "url": "https://github.com/MultipleChain/js/issues" }, "dependencies": { - "@multiplechain/types": "^0.1.30", - "@multiplechain/utils": "^0.1.14" + "@multiplechain/types": "^0.1.31", + "@multiplechain/utils": "^0.1.15" } } \ No newline at end of file diff --git a/packages/networks/evm-chains/package.json b/packages/networks/evm-chains/package.json index 7b158c3..ad4e3c8 100644 --- a/packages/networks/evm-chains/package.json +++ b/packages/networks/evm-chains/package.json @@ -50,8 +50,8 @@ "url": "https://github.com/MultipleChain/js/issues" }, "dependencies": { - "@multiplechain/types": "^0.1.30", - "@multiplechain/utils": "^0.1.14", + "@multiplechain/types": "^0.1.31", + "@multiplechain/utils": "^0.1.15", "@wagmi/chains": "^1.8.0", "ethers": "^6.11.1" } diff --git a/packages/networks/evm-chains/pnpm-lock.yaml b/packages/networks/evm-chains/pnpm-lock.yaml index 662fb8e..58df27e 100644 --- a/packages/networks/evm-chains/pnpm-lock.yaml +++ b/packages/networks/evm-chains/pnpm-lock.yaml @@ -6,11 +6,11 @@ settings: dependencies: '@multiplechain/types': - specifier: ^0.1.30 - version: 0.1.30 + specifier: ^0.1.31 + version: 0.1.31 '@multiplechain/utils': - specifier: ^0.1.14 - version: 0.1.14 + specifier: ^0.1.15 + version: 0.1.15 '@wagmi/chains': specifier: ^1.8.0 version: 1.8.0 @@ -24,12 +24,12 @@ packages: resolution: {integrity: sha512-96Z2IP3mYmF1Xg2cDm8f1gWGf/HUVedQ3FMifV4kG/PQ4yEP51xDtRAEfhVNt5f/uzpNkZHwWQuUcu6D6K+Ekw==} dev: false - /@multiplechain/types@0.1.30: - resolution: {integrity: sha512-j72Ydn1FlEWF4lY6xUjI0ojf0y1JAjqYnddAaUUdzv5sRlFw2zze8VLqxzltFtjFigPbSUa7QHmbgTIXQ60HoQ==} + /@multiplechain/types@0.1.31: + resolution: {integrity: sha512-p2RZJuh7v+beLdbdXL1EQ90qWeQcVW7Tfjrgl9xBeP1yR3EIc+68Mi6w117opOtMoi84oRYNSgDXvmjwVH5qQw==} dev: false - /@multiplechain/utils@0.1.14: - resolution: {integrity: sha512-MfpnKq8FHW0GgwSEeV3HprBUrJiCXW7PC3Ei1s3ii8wsWd46KC62a1+5fCuYk3fteupquxYYl72HhKhgbmczSA==} + /@multiplechain/utils@0.1.15: + resolution: {integrity: sha512-52jI4QAR3zNvk59TDvZ93xWNp96Vnx6fqXd4/XaVWcfITHwKJgfupnk/QqwaZsJ0a4IPxyz5AVtZ3pESwL7X+Q==} dependencies: '@types/ws': 8.5.10 bignumber.js: 9.1.2 diff --git a/packages/networks/evm-chains/src/services/Ethers.ts b/packages/networks/evm-chains/src/services/Ethers.ts index 73c82f2..4ad5180 100644 --- a/packages/networks/evm-chains/src/services/Ethers.ts +++ b/packages/networks/evm-chains/src/services/Ethers.ts @@ -53,20 +53,20 @@ export class Ethers { } /** - * @returns {WebSocketProvider | undefined} + * @returns {WebSocketProvider} */ - public async connectWebSocket(): Promise { + public async connectWebSocket(): Promise { return await new Promise((resolve, reject) => { if (this.network.wsUrl === undefined) { - resolve(undefined) + reject(new Error('WebSocket URL is not defined')) } else { const url = this.network.wsUrl checkWebSocket(url) .then((status) => { - if (status) { + if (status === true) { resolve((this.webSocketProvider = new WebSocketProvider(url))) } else { - resolve(undefined) + reject(new Error('WebSocket is not available')) } }) .catch(reject) diff --git a/packages/networks/evm-chains/src/services/Provider.ts b/packages/networks/evm-chains/src/services/Provider.ts index 0cf3019..f1fac9f 100644 --- a/packages/networks/evm-chains/src/services/Provider.ts +++ b/packages/networks/evm-chains/src/services/Provider.ts @@ -67,6 +67,36 @@ export class Provider implements Omit { Provider._instance = new Provider(network) } + /** + * Check RPC connection + * @param {string} url - RPC URL + * @returns {Promise} + */ + async checkConnection(url: string): Promise { + try { + const response = await fetch(url, { + method: 'POST', + headers: { + 'Content-Type': 'application/json' + }, + body: JSON.stringify({ + jsonrpc: '2.0', + method: 'eth_getChainId', + params: [], + id: 1 + }) + }) + + if (!response.ok) { + return new Error(response.statusText + ': ' + (await response.text())) + } + + return true + } catch (error) { + return error as any + } + } + /** * Update network configuration of the provider * @param {EvmNetworkConfigInterface} network - Network configuration of the provider diff --git a/packages/networks/evm-chains/src/services/TransactionListener.ts b/packages/networks/evm-chains/src/services/TransactionListener.ts index 1e4f432..df343f7 100644 --- a/packages/networks/evm-chains/src/services/TransactionListener.ts +++ b/packages/networks/evm-chains/src/services/TransactionListener.ts @@ -16,16 +16,16 @@ import { CoinTransaction } from '../models/CoinTransaction.ts' import { TokenTransaction } from '../models/TokenTransaction.ts' import { TransactionListenerProcessIndex } from '@multiplechain/types' import { ContractTransaction } from '../models/ContractTransaction.ts' -import type { - WebSocketProvider, - JsonRpcApiProvider, - EventFilter, - Log, - TransactionResponse +import { + type WebSocketProvider, + type JsonRpcApiProvider, + type EventFilter, + type Log, + type TransactionResponse } from 'ethers' export class TransactionListener - implements Omit, 'filter'> + implements TransactionListenerInterface { /** * Transaction type @@ -129,7 +129,7 @@ export class TransactionListener async on(callback: TransactionListenerCallbackType): Promise { if (this.webSocket === undefined) { const socket = await this.provider.ethers.connectWebSocket() - if (socket === undefined) { + if (typeof socket === 'string') { throw new Error('WebSocket connection is not available') } else { this.webSocket = socket From db097ec6a33c6e83eefc67f79ba7a49c9b4e6cb0 Mon Sep 17 00:00:00 2001 From: Halil Beycan <50718965+BeycanDeveloper@users.noreply.github.com> Date: Fri, 5 Apr 2024 18:13:44 +0800 Subject: [PATCH 103/114] updated --- packages/types/package.json | 2 +- packages/types/src/assets.ts | 112 ++++++++++-------- packages/types/src/models.ts | 48 ++++---- .../types/src/services/ProviderInterface.ts | 13 +- .../services/TransactionListenerInterface.ts | 13 +- .../services/TransactionSignerInterface.ts | 8 +- 6 files changed, 111 insertions(+), 85 deletions(-) diff --git a/packages/types/package.json b/packages/types/package.json index e9bce0e..6b3bf65 100644 --- a/packages/types/package.json +++ b/packages/types/package.json @@ -1,6 +1,6 @@ { "name": "@multiplechain/types", - "version": "0.1.31", + "version": "0.1.35", "type": "module", "main": "./src/index.ts", "types": "./src/index.ts", diff --git a/packages/types/src/assets.ts b/packages/types/src/assets.ts index 6e6f751..03a1226 100644 --- a/packages/types/src/assets.ts +++ b/packages/types/src/assets.ts @@ -13,20 +13,20 @@ export interface ContractInterface { address: string /** - * @returns Given contract address + * @returns {string} Given contract address */ getAddress: () => string /** - * @param method Method name - * @param args Method parameters + * @param {string} method Method name + * @param {any[]} args Method parameters * Runs the contract methods dynamically */ callMethod: (method: string, ...args: any[]) => Promise /** - * @param method Method name - * @param args Method parameters + * @param {string} method Method name + * @param {any[]} args Method parameters * To get information from called method * @returns Data used in transaction */ @@ -35,26 +35,27 @@ export interface ContractInterface { export interface AssetInterface { /** - * @returns Name of the asset (long name) + * @returns {string} Name of the asset (long name) */ getName: () => string /** - * @returns Symbol of the asset (short name) + * @returns {string} Symbol of the asset (short name) */ getSymbol: () => string /** - * @param owner Address of the wallet - * @returns Wallet balance as currency of TOKEN or COIN assets + * @param {string} owner Address of the wallet + * @returns {Promise} Wallet balance as currency of TOKEN or COIN assets */ getBalance: (owner: string) => Promise /** * transfer() method is the main method for processing transfers for fungible assets (TOKEN, COIN) - * @param sender Sender wallet address - * @param receiver Receiver wallet address - * @param amount Amount of assets that will be transferred + * @param {string} sender Sender wallet address + * @param {string} receiver Receiver wallet address + * @param {number} amount Amount of assets that will be transferred + * @returns {Promise} Transaction signer interface */ transfer: ( sender: string, @@ -66,7 +67,7 @@ export interface AssetInterface { // Sub Interfaces export interface CoinInterface extends AssetInterface { /** - * @returns Decimal value of the coin + * @returns {number} Decimal value of the coin */ getDecimals: () => number } @@ -75,38 +76,38 @@ export interface TokenInterface extends Omit, ContractInterface { /** - * @returns Name of the asset (long name) + * @returns {Promise} Name of the asset (long name) */ getName: () => Promise /** - * @returns Symbol of the asset (short name) + * @returns {Promise} Symbol of the asset (short name) */ getSymbol: () => Promise /** - * @returns Decimal value of the token + * @returns {Promise} Decimal value of the token */ getDecimals: () => Promise /** - * @returns Total supply of the token + * @returns {Promise} Total supply of the token */ getTotalSupply: () => Promise /** - * @param owner Address of owner of the tokens that is being used - * @param spender Address of the spender that is using the tokens of owner - * @returns Amount of the tokens that is being used by spender + * @param {string} owner Address of owner of the tokens that is being used + * @param {string} spender Address of the spender that is using the tokens of owner + * @returns {Promise} Amount of the tokens that is being used by spender */ getAllowance: (owner: string, spender: string) => Promise /** - * @param spender Address of the spender of transaction - * @param owner Sender wallet address - * @param receiver Receiver wallet address - * @param amount Amount of tokens that will be transferred - * @override transfer() in AssetInterface + * @param {string} spender Address of the spender of transaction + * @param {string} owner Sender wallet address + * @param {string} receiver Receiver wallet address + * @param {number} amount Amount of tokens that will be transferred + * @returns {Promise} Transaction signer interface */ transferFrom: ( spender: string, @@ -117,9 +118,10 @@ export interface TokenInterface /** * Gives permission to the spender to spend owner's tokens - * @param owner Address of owner of the tokens that will be used - * @param spender Address of the spender that is using the tokens of owner - * @param amount Amount of the tokens that will be used + * @param {string} owner Address of owner of the tokens that will be used + * @param {string} spender Address of the spender that is using the tokens of owner + * @param {number} amount Amount of the tokens that will be used + * @returns {Promise} Transaction signer interface */ approve: (owner: string, spender: string, amount: number) => Promise } @@ -128,64 +130,70 @@ export interface NftInterface extends Omit, ContractInterface { /** - * @returns Name of the asset (long name) + * @returns {Promise} Name of the asset (long name) */ getName: () => Promise /** - * @returns Symbol of the asset (short name) + * @returns {Promise} Symbol of the asset (short name) */ getSymbol: () => Promise /** - * @param nftId ID of the NFT - * @returns Wallet address of owner of the NFT + * @param {number | string} nftId ID of the NFT + * @returns {Promise} Wallet address of owner of the NFT */ - getOwner: (nftId: number) => Promise + getOwner: (nftId: number | string) => Promise /** - * @param nftId ID of the NFT - * @returns URL of the metadata + * @param {number | string} nftId ID of the NFT + * @returns {Promise} URL of the metadata */ - getTokenURI: (nftId: number) => Promise + getTokenURI: (nftId: number | string) => Promise /** - * @param nftId ID of the NFT that will be transferred - * @returns Amount of the tokens that is being used by spender + * @param {number | string} nftId ID of the NFT that will be transferred + * @returns {Promise} Amount of the tokens that is being used by spender */ - getApproved: (nftId: number) => Promise + getApproved: (nftId: number | string) => Promise /** * Transfers an NFT - * @param sender Sender wallet address - * @param receiver Receiver wallet address - * @param nftId ID of the NFT that will be transferred + * @param {string} sender Sender wallet address + * @param {string} receiver Receiver wallet address + * @param {number | string} nftId ID of the NFT that will be transferred * @override transfer() in AssetInterface + * @returns {Promise} Transaction signer interface */ transfer: ( sender: string, receiver: string, - nftId: number + nftId: number | string ) => Promise /** - * @param spender Address of the spender of transaction - * @param owner Address of owner of the nfts that will be used - * @param receiver Address of the receiver that will receive the nfts - * @param nftId ID of the NFT that will be transferred + * @param {string} spender Address of the spender of transaction + * @param {string} owner Address of owner of the nfts that will be used + * @param {string} receiver Address of the receiver that will receive the nfts + * @param {number | string} nftId ID of the NFT that will be transferred + * @returns {Promise} Transaction signer interface */ transferFrom: ( spender: string, owner: string, receiver: string, - nftId: number + nftId: number | string ) => Promise /** * Gives permission to the spender to spend owner's tokens - * @param owner Address of owner of the tokens that will be used - * @param spender Address of the spender that will use the tokens of owner - * @param nftId ID of the NFT that will be transferred + * @param {string} owner Address of owner of the tokens that will be used + * @param {string} spender Address of the spender that will use the tokens of owner + * @param {number | string} nftId ID of the NFT that will be transferred */ - approve: (owner: string, spender: string, nftId: number) => Promise + approve: ( + owner: string, + spender: string, + nftId: number | string + ) => Promise } diff --git a/packages/types/src/models.ts b/packages/types/src/models.ts index ac0c068..9d8df91 100644 --- a/packages/types/src/models.ts +++ b/packages/types/src/models.ts @@ -7,84 +7,85 @@ export interface TransactionInterface { id: string /** - * @returns Promise of the transaction status + * @returns {Promise} Promise of the transaction status */ wait: () => Promise /** - * @returns Raw transaction data that is taken by blockchain network via RPC. + * @returns {Promise} Raw transaction data that is taken by blockchain network via RPC. */ getData: () => Promise /** - * @returns Transaction id from the blockchain network + * @returns {string} ID of the transaction * this can be different names like txid, hash, signature etc. */ getId: () => string /** - * @returns Blockchain explorer URL of the transaction. Dependant on network. + * @returns {string} Blockchain explorer URL of the transaction. Dependant on network. */ getUrl: () => string /** - * @returns Wallet address of the signer of transaction + * @returns {Promise} Wallet address of the signer of transaction */ getSigner: () => Promise /** - * @returns Transaction fee as native coin amount + * @returns {Promise} Transaction fee as native coin amount */ getFee: () => Promise /** - * @returns Block ID of the transaction + * @returns {Promise} Block ID of the transaction */ getBlockNumber: () => Promise /** - * @returns UNIX timestamp of the date that block is added to blockchain + * @returns {Promise} UNIX timestamp of the date that block is added to blockchain */ getBlockTimestamp: () => Promise /** - * @returns Block confirmation amount + * @returns {Promise} Block confirmation amount */ getBlockConfirmationCount: () => Promise /** - * @returns Status of the transaction. + * @returns {Promise} Status of the transaction. */ getStatus: () => Promise } export interface ContractTransactionInterface extends TransactionInterface { /** - * @returns Smart contract address of the transaction + * @returns {Promise} Smart contract address of the transaction */ getAddress: () => Promise } export interface AssetTransactionInterface extends TransactionInterface { /** - * @returns Receiver wallet address of the transaction (asset) + * @returns {Promise} Receiver wallet address of the transaction (asset) */ getReceiver: () => Promise /** - * @returns Wallet address of the sender of asset + * @returns {Promise} Wallet address of the sender of asset */ getSender: () => Promise /** - * @returns Transfer amount of the transaction (coin) + * @returns {Promise} Transfer amount of the transaction (coin) */ getAmount: () => Promise /** - * @param direction - Direction of the transaction (asset) - * @param address - Wallet address of the receiver or sender of the transaction, dependant on direction - * @param amount Amount of assets that will be transferred + * @param {AssetDirectionEnum} direction - Direction of the transaction (asset) + * @param {string} address - Wallet address of the receiver or sender of the transaction, dependant on direction + * @param {number} amount Amount of assets that will be transferred + * @returns {Promise} Status of the transaction */ verifyTransfer: ( direction: AssetDirectionEnum, @@ -103,19 +104,20 @@ export interface NftTransactionInterface extends Omit, ContractTransactionInterface { /** - * @returns ID of the NFT + * @returns {Promise} ID of the NFT */ - getNftId: () => Promise + getNftId: () => Promise /** - * @param direction - Direction of the transaction (nft) - * @param address - Wallet address of the receiver or sender of the transaction, dependant on direction - * @param nftId ID of the NFT that will be transferred + * @param {AssetDirectionEnum} direction - Direction of the transaction (nft) + * @param {string} address - Wallet address of the receiver or sender of the transaction, dependant on direction + * @param {number | string} nftId ID of the NFT that will be transferred * @override verifyTransfer() in AssetTransactionInterface + * @returns {Promise} Status of the transaction */ verifyTransfer: ( direction: AssetDirectionEnum, address: string, - nftId: number + nftId: number | string ) => Promise } diff --git a/packages/types/src/services/ProviderInterface.ts b/packages/types/src/services/ProviderInterface.ts index 91e2ef9..75ff200 100644 --- a/packages/types/src/services/ProviderInterface.ts +++ b/packages/types/src/services/ProviderInterface.ts @@ -17,16 +17,27 @@ export interface ProviderInterface { /** * Update network configuration of the provider + * @param {NetworkConfigInterface} network - Network configuration */ update: (network: NetworkConfigInterface) => void /** * Get the current network configuration is testnet or not + * @returns {boolean} */ isTestnet: () => boolean /** * Check RPC connection + * @param {string} url - RPC URL + * @returns {Promise} */ - checkConnection: (url: string) => Promise + checkRpcConnection: (url?: string) => Promise + + /** + * Check WS connection + * @param {string} url - Websocket URL + * @returns {Promise} + */ + checkWsConnection: (url?: string) => Promise } diff --git a/packages/types/src/services/TransactionListenerInterface.ts b/packages/types/src/services/TransactionListenerInterface.ts index b3d3764..ff277ac 100644 --- a/packages/types/src/services/TransactionListenerInterface.ts +++ b/packages/types/src/services/TransactionListenerInterface.ts @@ -37,7 +37,7 @@ interface TokenTransactionListenerFilterInterface interface NftTransactionListenerFilterInterface extends AssetTransactionListenerFilterInterface, ContractTransactionListenerFilterInterface { - nftId?: number + nftId?: number | string } /** * Filter types for each transaction type in TransactionListenerInterface @@ -125,29 +125,34 @@ export interface TransactionListenerInterface { /** * stop() method closes the corresponding listener of the instance it's called from. + * @returns {void} */ stop: () => void /** * start() method starts the corresponding listener of the instance it's called from. + * @returns {void} */ start: () => void /** * getStatus() method returns the status of the listener. + * @returns {boolean} */ getStatus: () => boolean /** * on() method is a listener that listens to the transaction events. * When a transaction is detected, it triggers the event. - * @param callback - a function that is triggered when a transaction is detected. + * @param {TransactionListenerCallbackType} callback - a function that is triggered when a transaction is detected. + * @return {Promise} */ - on: (callback: TransactionListenerCallbackType) => void + on: (callback: TransactionListenerCallbackType) => Promise /** * trigger() method triggers the event when a transaction is detected. - * @param transaction - the transaction that is detected + * @param {DynamicTransactionType} transaction - a transaction that is detected. + * @return {void} */ trigger: (transaction: DynamicTransactionType) => void diff --git a/packages/types/src/services/TransactionSignerInterface.ts b/packages/types/src/services/TransactionSignerInterface.ts index cac39d9..4966879 100644 --- a/packages/types/src/services/TransactionSignerInterface.ts +++ b/packages/types/src/services/TransactionSignerInterface.ts @@ -16,22 +16,22 @@ export interface TransactionSignerInterface { signedData?: any /** - * @param privateKey - Private key of the wallet to sign the transaction + * @param {string} privateKey - Private key of the wallet to sign the transaction */ sign: (privateKey: string) => Promise /** - * @returns Send the transaction to the blockchain network, returns a promise of the transaction + * @returns {Promise} Send the transaction to the blockchain network, returns a promise of the transaction */ send: () => Promise /** - * @returns Unsigned transaction raw data + * @returns {any} Unsigned transaction raw data */ getRawData: () => any /** - * @returns Signed transaction data + * @returns {any} Signed transaction data */ getSignedData: () => any } From 78234060bbd920d6fd53a29a8542c959811f7e0d Mon Sep 17 00:00:00 2001 From: Halil Beycan <50718965+BeycanDeveloper@users.noreply.github.com> Date: Fri, 5 Apr 2024 18:41:48 +0800 Subject: [PATCH 104/114] configurations --- .eslintrc.json | 2 +- packages/networks/boilerplate/package.json | 2 +- packages/networks/boilerplate/tsconfig.json | 10 +++++- packages/networks/evm-chains/package.json | 2 +- packages/networks/evm-chains/pnpm-lock.yaml | 8 ++--- .../networks/evm-chains/src/assets/NFT.ts | 32 ++++++++++++------- .../evm-chains/src/models/NftTransaction.ts | 8 ++--- .../evm-chains/src/services/Provider.ts | 25 +++++++++++++-- .../src/services/TransactionListener.ts | 2 +- packages/networks/evm-chains/tsconfig.json | 11 ++++++- tsconfig.json | 6 ++-- 11 files changed, 78 insertions(+), 30 deletions(-) diff --git a/.eslintrc.json b/.eslintrc.json index 345e634..e406f00 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -25,5 +25,5 @@ "rules": { "filenames/match-exported": ["error", "pascal"] }, - "ignorePatterns": ["**/*.d.ts", "dist/", "node_modules/"] + "ignorePatterns": ["**/*.d.ts", "dist/", "node_modules/", "test*.ts"] } diff --git a/packages/networks/boilerplate/package.json b/packages/networks/boilerplate/package.json index e69eca7..eb481d0 100644 --- a/packages/networks/boilerplate/package.json +++ b/packages/networks/boilerplate/package.json @@ -47,7 +47,7 @@ "url": "https://github.com/MultipleChain/js/issues" }, "dependencies": { - "@multiplechain/types": "^0.1.31", + "@multiplechain/types": "^0.1.35", "@multiplechain/utils": "^0.1.15" } } \ No newline at end of file diff --git a/packages/networks/boilerplate/tsconfig.json b/packages/networks/boilerplate/tsconfig.json index 40bb104..0b582a6 100644 --- a/packages/networks/boilerplate/tsconfig.json +++ b/packages/networks/boilerplate/tsconfig.json @@ -7,5 +7,13 @@ "declarationDir": "./dist/types" }, "extends": "../../../tsconfig.json", - "include": ["src", ".eslintrc.json", "tests"] + "include": [ + "src", + ".eslintrc.json", + "tests", + "vite.config.ts", + "esbuild.ts", + "../../../esbuild.ts", + "../../../vite.config.ts" + ] } diff --git a/packages/networks/evm-chains/package.json b/packages/networks/evm-chains/package.json index ad4e3c8..44aa498 100644 --- a/packages/networks/evm-chains/package.json +++ b/packages/networks/evm-chains/package.json @@ -50,7 +50,7 @@ "url": "https://github.com/MultipleChain/js/issues" }, "dependencies": { - "@multiplechain/types": "^0.1.31", + "@multiplechain/types": "^0.1.35", "@multiplechain/utils": "^0.1.15", "@wagmi/chains": "^1.8.0", "ethers": "^6.11.1" diff --git a/packages/networks/evm-chains/pnpm-lock.yaml b/packages/networks/evm-chains/pnpm-lock.yaml index 58df27e..0ba8652 100644 --- a/packages/networks/evm-chains/pnpm-lock.yaml +++ b/packages/networks/evm-chains/pnpm-lock.yaml @@ -6,8 +6,8 @@ settings: dependencies: '@multiplechain/types': - specifier: ^0.1.31 - version: 0.1.31 + specifier: ^0.1.35 + version: 0.1.35 '@multiplechain/utils': specifier: ^0.1.15 version: 0.1.15 @@ -24,8 +24,8 @@ packages: resolution: {integrity: sha512-96Z2IP3mYmF1Xg2cDm8f1gWGf/HUVedQ3FMifV4kG/PQ4yEP51xDtRAEfhVNt5f/uzpNkZHwWQuUcu6D6K+Ekw==} dev: false - /@multiplechain/types@0.1.31: - resolution: {integrity: sha512-p2RZJuh7v+beLdbdXL1EQ90qWeQcVW7Tfjrgl9xBeP1yR3EIc+68Mi6w117opOtMoi84oRYNSgDXvmjwVH5qQw==} + /@multiplechain/types@0.1.35: + resolution: {integrity: sha512-szg+arayBvT3WivUa9l6ZYjS6tNjhFMDpQCcAUL94s5yWpDM73OnHMA861XVVVY0xIUgJpzCj32PlJU+CARYow==} dev: false /@multiplechain/utils@0.1.15: diff --git a/packages/networks/evm-chains/src/assets/NFT.ts b/packages/networks/evm-chains/src/assets/NFT.ts index 552af06..35e3cfd 100644 --- a/packages/networks/evm-chains/src/assets/NFT.ts +++ b/packages/networks/evm-chains/src/assets/NFT.ts @@ -38,36 +38,40 @@ export class NFT extends Contract implements NftInterface { } /** - * @param {number} nftId NFT ID + * @param {number | string} nftId NFT ID * @returns {Promise} Wallet address of the owner of the NFT */ - async getOwner(nftId: number): Promise { + async getOwner(nftId: number | string): Promise { return await this.callMethod('ownerOf', nftId) } /** - * @param {number} nftId NFT ID + * @param {number | string} nftId NFT ID * @returns {Promise} URI of the NFT */ - async getTokenURI(nftId: number): Promise { + async getTokenURI(nftId: number | string): Promise { return await this.callMethod('tokenURI', nftId) } /** - * @param {number} nftId ID of the NFT that will be transferred + * @param {number | string} nftId ID of the NFT that will be transferred * @returns {Promise} Wallet address of the approved spender */ - async getApproved(nftId: number): Promise { + async getApproved(nftId: number | string): Promise { return await this.callMethod('getApproved', nftId) } /** * @param {string} sender Sender address * @param {string} receiver Receiver address - * @param {number} nftId NFT ID + * @param {number | string} nftId NFT ID * @returns {Promise} Transaction signer */ - async transfer(sender: string, receiver: string, nftId: number): Promise { + async transfer( + sender: string, + receiver: string, + nftId: number | string + ): Promise { return await this.transferFrom(sender, sender, receiver, nftId) } @@ -75,14 +79,14 @@ export class NFT extends Contract implements NftInterface { * @param {string} spender Spender address * @param {string} owner Owner address * @param {string} receiver Receiver address - * @param {number} nftId NFT ID + * @param {number | string} nftId NFT ID * @returns {Promise} Transaction signer */ async transferFrom( spender: string, owner: string, receiver: string, - nftId: number + nftId: number | string ): Promise { // Check if tokens exist const balance = await this.getBalance(owner) @@ -128,10 +132,14 @@ export class NFT extends Contract implements NftInterface { * Gives permission to the spender to spend owner's tokens * @param {string} owner Address of owner of the tokens that will be used * @param {string} spender Address of the spender that will use the tokens of owner - * @param {number} nftId ID of the NFT that will be transferred + * @param {number | string} nftId ID of the NFT that will be transferred * @returns {Promise} Transaction signer */ - async approve(owner: string, spender: string, nftId: number): Promise { + async approve( + owner: string, + spender: string, + nftId: number | string + ): Promise { // Check if tokens exist const balance = await this.getBalance(owner) diff --git a/packages/networks/evm-chains/src/models/NftTransaction.ts b/packages/networks/evm-chains/src/models/NftTransaction.ts index 08fcec2..ebc8f27 100644 --- a/packages/networks/evm-chains/src/models/NftTransaction.ts +++ b/packages/networks/evm-chains/src/models/NftTransaction.ts @@ -50,23 +50,23 @@ export class NftTransaction extends ContractTransaction implements NftTransactio } /** - * @returns {Promise} NFT ID + * @returns {Promise} NFT ID */ - async getNftId(): Promise { + async getNftId(): Promise { return Number((await this.decodeData())?.args[2] ?? 0) } /** * @param {AssetDirectionEnum} direction - Direction of the transaction (nft) * @param {string} address - Wallet address of the receiver or sender of the transaction, dependant on direction - * @param {number} nftId ID of the NFT that will be transferred + * @param {number | string} nftId ID of the NFT that will be transferred * @override verifyTransfer() in AssetTransactionInterface * @returns {Promise} Status of the transaction */ async verifyTransfer( direction: AssetDirectionEnum, address: string, - nftId: number + nftId: number | string ): Promise { const status = await this.getStatus() diff --git a/packages/networks/evm-chains/src/services/Provider.ts b/packages/networks/evm-chains/src/services/Provider.ts index f1fac9f..81204ba 100644 --- a/packages/networks/evm-chains/src/services/Provider.ts +++ b/packages/networks/evm-chains/src/services/Provider.ts @@ -5,6 +5,8 @@ import { type ProviderInterface } from '@multiplechain/types' +import { checkWebSocket } from '@multiplechain/utils' + export interface EvmNetworkConfigInterface extends NetworkConfigInterface { id: number hexId?: string @@ -72,9 +74,9 @@ export class Provider implements Omit { * @param {string} url - RPC URL * @returns {Promise} */ - async checkConnection(url: string): Promise { + async checkRpcConnection(url?: string): Promise { try { - const response = await fetch(url, { + const response = await fetch(url ?? this.network.rpcUrl, { method: 'POST', headers: { 'Content-Type': 'application/json' @@ -97,6 +99,25 @@ export class Provider implements Omit { } } + /** + * Check WS connection + * @param {string} url - Websocket URL + * @returns {Promise} + */ + async checkWsConnection(url?: string): Promise { + try { + const result = await checkWebSocket(url ?? this.network.rpcUrl) + + if (result === true) { + return true + } + + return new Error(result as string) + } catch (error) { + return error as Error + } + } + /** * Update network configuration of the provider * @param {EvmNetworkConfigInterface} network - Network configuration of the provider diff --git a/packages/networks/evm-chains/src/services/TransactionListener.ts b/packages/networks/evm-chains/src/services/TransactionListener.ts index df343f7..b513638 100644 --- a/packages/networks/evm-chains/src/services/TransactionListener.ts +++ b/packages/networks/evm-chains/src/services/TransactionListener.ts @@ -124,7 +124,7 @@ export class TransactionListener /** * Listen to the transaction events * @param {TransactionListenerCallbackType} callback - Callback function - * @returns {void} + * @returns {Promise} */ async on(callback: TransactionListenerCallbackType): Promise { if (this.webSocket === undefined) { diff --git a/packages/networks/evm-chains/tsconfig.json b/packages/networks/evm-chains/tsconfig.json index ea36f83..7f458a3 100644 --- a/packages/networks/evm-chains/tsconfig.json +++ b/packages/networks/evm-chains/tsconfig.json @@ -7,5 +7,14 @@ "declarationDir": "./dist/types" }, "extends": "../../../tsconfig.json", - "include": ["src", ".eslintrc.json", "tests", "resources/*.json"] + "include": [ + "src", + ".eslintrc.json", + "tests", + "resources/*.json", + "vite.config.ts", + "esbuild.ts", + "../../../esbuild.ts", + "../../../vite.config.ts" + ] } diff --git a/tsconfig.json b/tsconfig.json index 08215d8..20ad9df 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,5 +1,6 @@ { "compilerOptions": { + "rootDir": "./", "declaration": true, "types": ["node"], "target": "ES2020", @@ -23,12 +24,13 @@ "strictPropertyInitialization": false }, "include": [ + "packages/networks/**/*.ts", "packages/**/*.ts", ".eslintrc.json", "vite.config.ts", "vitest.config.ts", "vite-env.d.ts", - "esbuild.ts" + "esbuild.ts", ], - "exclude": ["node_modules", "dist", "packages/**/*.d.ts"] + "exclude": ["node_modules", "dist", "packages/**/*.d.ts", "test*.ts"] } From 519576775a8ef9a5ad294c37963a180ce1f7fb0d Mon Sep 17 00:00:00 2001 From: Halil Beycan <50718965+BeycanDeveloper@users.noreply.github.com> Date: Fri, 5 Apr 2024 20:18:21 +0800 Subject: [PATCH 105/114] added dynamic type creator for networks --- packages/networks/evm-chains/cdt.ts | 22 ++++++++++++++++ packages/networks/evm-chains/package.json | 2 +- packages/networks/evm-chains/src/index.ts | 9 +------ .../evm-chains/src/services/Networks.ts | 25 ++++++++++++------- 4 files changed, 40 insertions(+), 18 deletions(-) create mode 100644 packages/networks/evm-chains/cdt.ts diff --git a/packages/networks/evm-chains/cdt.ts b/packages/networks/evm-chains/cdt.ts new file mode 100644 index 0000000..f66dd57 --- /dev/null +++ b/packages/networks/evm-chains/cdt.ts @@ -0,0 +1,22 @@ +// Create dynamic types + +import fs from 'fs' +import { networks } from './src/index.ts' + +console.log('\r\nCreating dynamic types...') + +const networkTypes: string[] = [] + +Object.entries(networks).forEach(([key, value]) => { + if (typeof value === 'object' && key !== '__esModule') { + const type = ` ${key}: EvmNetworkConfigInterface;` + networkTypes.push(type) + } +}) + +const content = fs.readFileSync('./dist/services/Networks.d.ts', 'utf-8') +const insertIndex = content.lastIndexOf('}') +const updatedContent = + content.slice(0, insertIndex) + networkTypes.join('\n') + '\n' + content.slice(insertIndex) + +fs.writeFileSync('./dist/services/Networks.d.ts', updatedContent) diff --git a/packages/networks/evm-chains/package.json b/packages/networks/evm-chains/package.json index 44aa498..90d1a1e 100644 --- a/packages/networks/evm-chains/package.json +++ b/packages/networks/evm-chains/package.json @@ -28,7 +28,7 @@ "lint": "eslint . --ext .ts", "test": "vitest run --dir tests", "prepublishOnly": "pnpm run build", - "build": "pnpm run build:vite && pnpm run build:node" + "build": "pnpm run build:vite && pnpm run build:node && tsx cdt.ts" }, "keywords": [ "web3", diff --git a/packages/networks/evm-chains/src/index.ts b/packages/networks/evm-chains/src/index.ts index 9c367a9..f174cc8 100644 --- a/packages/networks/evm-chains/src/index.ts +++ b/packages/networks/evm-chains/src/index.ts @@ -1,15 +1,8 @@ -import allNetworks, * as methods from './services/Networks.ts' - export * from './services/Provider.ts' export * as assets from './assets/index.ts' export * as models from './models/index.ts' export * as services from './services/index.ts' - +export { default as networks } from './services/Networks.ts' export * as utils from '@multiplechain/utils' export * as types from '@multiplechain/types' - -export const networks = { - ...methods, - ...allNetworks -} diff --git a/packages/networks/evm-chains/src/services/Networks.ts b/packages/networks/evm-chains/src/services/Networks.ts index ac3a6cc..5b9437f 100644 --- a/packages/networks/evm-chains/src/services/Networks.ts +++ b/packages/networks/evm-chains/src/services/Networks.ts @@ -42,24 +42,31 @@ Object.keys(wagmiChains).forEach((key) => { networks[key === 'mainnet' ? 'ethereum' : key] = network }) -export const findByKey = (key: string): EvmNetworkConfigInterface | undefined => { - return networks[key] +const findById = (id: number): EvmNetworkConfigInterface | undefined => { + return Object.values(networks).find((network) => network.id === id) } -export const findByName = (name: string): EvmNetworkConfigInterface | undefined => { - return Object.values(networks).find((network) => network.name?.includes(name)) +const findByKey = (key: string): EvmNetworkConfigInterface | undefined => { + return networks[key] } -export const findById = (id: number): EvmNetworkConfigInterface | undefined => { - return Object.values(networks).find((network) => network.id === id) +const findByName = (name: string): EvmNetworkConfigInterface | undefined => { + return Object.values(networks).find((network) => network.name?.includes(name)) } -export const findByHexId = (hexId: string): EvmNetworkConfigInterface | undefined => { +const findByHexId = (hexId: string): EvmNetworkConfigInterface | undefined => { return Object.values(networks).find((network) => network.hexId === hexId) } -export const findBySymbol = (symbol: string): EvmNetworkConfigInterface | undefined => { +const findBySymbol = (symbol: string): EvmNetworkConfigInterface | undefined => { return Object.values(networks).find((network) => network.nativeCurrency.symbol === symbol) } -export default networks +export default { + findById, + findByKey, + findByName, + findByHexId, + findBySymbol, + ...networks +} From 8b03c36dfc13564a018790d92a18b98138e877ce Mon Sep 17 00:00:00 2001 From: Halil Beycan <50718965+BeycanDeveloper@users.noreply.github.com> Date: Fri, 5 Apr 2024 20:25:27 +0800 Subject: [PATCH 106/114] added getTestnets and getMainnets --- packages/networks/evm-chains/cdt.ts | 2 ++ packages/networks/evm-chains/src/services/Networks.ts | 10 ++++++++++ 2 files changed, 12 insertions(+) diff --git a/packages/networks/evm-chains/cdt.ts b/packages/networks/evm-chains/cdt.ts index f66dd57..e6c4aa6 100644 --- a/packages/networks/evm-chains/cdt.ts +++ b/packages/networks/evm-chains/cdt.ts @@ -20,3 +20,5 @@ const updatedContent = content.slice(0, insertIndex) + networkTypes.join('\n') + '\n' + content.slice(insertIndex) fs.writeFileSync('./dist/services/Networks.d.ts', updatedContent) + +console.log('Dynamic types created successfully!') diff --git a/packages/networks/evm-chains/src/services/Networks.ts b/packages/networks/evm-chains/src/services/Networks.ts index 5b9437f..cfc7b00 100644 --- a/packages/networks/evm-chains/src/services/Networks.ts +++ b/packages/networks/evm-chains/src/services/Networks.ts @@ -62,11 +62,21 @@ const findBySymbol = (symbol: string): EvmNetworkConfigInterface | undefined => return Object.values(networks).find((network) => network.nativeCurrency.symbol === symbol) } +const getTestnets = (): EvmNetworkConfigInterface[] => { + return Object.values(networks).filter((network) => network.testnet ?? false) +} + +const getMainnets = (): EvmNetworkConfigInterface[] => { + return Object.values(networks).filter((network) => !(network.testnet ?? false)) +} + export default { findById, findByKey, findByName, findByHexId, findBySymbol, + getTestnets, + getMainnets, ...networks } From aae74639fcf9564e98a60996bd51ae01aa99bba8 Mon Sep 17 00:00:00 2001 From: Halil Beycan <50718965+BeycanDeveloper@users.noreply.github.com> Date: Fri, 5 Apr 2024 21:11:57 +0800 Subject: [PATCH 107/114] test configurations --- .gitignore | 1 + package.json | 1 + packages/networks/boilerplate/tests/setup.ts | 0 packages/networks/boilerplate/tsconfig.json | 4 +- .../networks/boilerplate/vitest.config.ts | 11 +++++ packages/networks/evm-chains/.env.example | 49 +++++++++++++++++++ .../evm-chains/src/models/NftTransaction.ts | 2 +- .../evm-chains/src/models/TokenTransaction.ts | 2 +- .../networks/evm-chains/tests/assets.spec.ts | 44 +++++++++-------- .../networks/evm-chains/tests/models.spec.ts | 24 ++++----- packages/networks/evm-chains/tests/setup.ts | 45 ++++++----------- packages/networks/evm-chains/tsconfig.json | 5 +- packages/networks/evm-chains/vitest.config.ts | 12 +++++ pnpm-lock.yaml | 19 +++++++ vite.config.ts | 4 +- vitest.config.ts | 3 +- 16 files changed, 155 insertions(+), 71 deletions(-) create mode 100644 packages/networks/boilerplate/tests/setup.ts create mode 100644 packages/networks/boilerplate/vitest.config.ts create mode 100644 packages/networks/evm-chains/.env.example create mode 100644 packages/networks/evm-chains/vitest.config.ts diff --git a/.gitignore b/.gitignore index 6bc6b68..09d282a 100644 --- a/.gitignore +++ b/.gitignore @@ -16,6 +16,7 @@ index.html test*.ts test*.js test*.cjs +.env # Editor directories and files .vscode/* diff --git a/package.json b/package.json index a841273..708c919 100644 --- a/package.json +++ b/package.json @@ -30,6 +30,7 @@ "typescript": "^5.3.3", "vite": "^5.1.4", "vite-plugin-dts": "^3.8.1", + "vite-plugin-env-compatible": "^2.0.1", "vite-plugin-node-polyfills": "^0.21.0", "vitest": "^1.3.1" } diff --git a/packages/networks/boilerplate/tests/setup.ts b/packages/networks/boilerplate/tests/setup.ts new file mode 100644 index 0000000..e69de29 diff --git a/packages/networks/boilerplate/tsconfig.json b/packages/networks/boilerplate/tsconfig.json index 0b582a6..e40c547 100644 --- a/packages/networks/boilerplate/tsconfig.json +++ b/packages/networks/boilerplate/tsconfig.json @@ -13,7 +13,9 @@ "tests", "vite.config.ts", "esbuild.ts", + "vitest.config.ts", "../../../esbuild.ts", - "../../../vite.config.ts" + "../../../vite.config.ts", + "../../../vitest.config.ts", ] } diff --git a/packages/networks/boilerplate/vitest.config.ts b/packages/networks/boilerplate/vitest.config.ts new file mode 100644 index 0000000..73ee32b --- /dev/null +++ b/packages/networks/boilerplate/vitest.config.ts @@ -0,0 +1,11 @@ +import { mergeConfig, defineConfig } from 'vitest/config' +import mainConfig from '../../../vite.config.ts' + +export default mergeConfig( + mainConfig, + defineConfig({ + test: { + setupFiles: ['./tests/setup.ts'] + } + }) +) diff --git a/packages/networks/evm-chains/.env.example b/packages/networks/evm-chains/.env.example new file mode 100644 index 0000000..618e685 --- /dev/null +++ b/packages/networks/evm-chains/.env.example @@ -0,0 +1,49 @@ +RPC_URL='https://sepolia.infura.io/v3/9aa3d95b3bc440fa88ea12eaa4456161' +WS_URL='wss://sepolia.infura.io/ws/v3/9aa3d95b3bc440fa88ea12eaa4456161' + +BACKUP_RPC_URL='https://dimensional-icy-tent.ethereum-sepolia.quiknode.pro/e6a31d965b3ab5fc57d5980d187121f1894c0eb4/' +BACKUP_WS_URL='wss://dimensional-icy-tent.ethereum-sepolia.quiknode.pro/ws/e6a31d965b3ab5fc57d5980d187121f1894c0eb4/' + +# Assets +COIN_TRANSFER_TEST_IS_ACTIVE=true +TOKEN_TRANSFER_TEST_IS_ACTIVE=false +TOKEN_APPROVE_TEST_IS_ACTIVE=false +TOKEN_TRANSFER_FROM_TEST_IS_ACTIVE=false +NFT_TRANSACTION_TEST_IS_ACTIVE=false + +COIN_BALANCE_TEST_AMOUNT=0.01 +TOKEN_BALANCE_TEST_AMOUNT=1000 +NFT_BALANCE_TEST_AMOUNT=2 +TRANSFER_TEST_AMOUNT=0.0001 +TOKEN_TRANSFER_TEST_AMOUNT=1 +TOKEN_APPROVE_TEST_AMOUNT=100 +NFT_TRANSFER_ID=7 + +BALANCE_TEST_ADDRESS='0x760A4d3D03928D1e8541A7644B34370c1b79aa9F' +SENDER_PRIVATE_KEY='0x14bd9af4e87981b37b7b2e8a0d1d249b7fcdb7a3bc579c4c31488842d372c0e9' +RECEIVER_PRIVATE_KEY='0x22ac1009c43f251e0b5a808751990abe77a74fe12f390c0cc95ab179a0b61a5a' +SENDER_TEST_ADDRESS='0x110600bF0399174520a159ed425f0D272Ff8b459' +RECEIVER_TEST_ADDRESS='0xbBa4d06D1cEf94b35aDeCfDa893523907fdD36DE' +TOKEN_TEST_ADDRESS='0x4294cb0dD25dC9140B5127f247cBd47Eeb673431' +NFT_TEST_ADDRESS='0x06B8B36e4feD2206E980445C0f0829fc6B2aA91F' +# Assets + +# Models +NFT_ID=7 +TOKEN_AMOUNT=1 +COIN_AMOUNT=0.002548 + +COIN_SENDER='0x74dBE9cA4F93087A27f23164d4367b8ce66C33e2' +COIN_RECEIVER='0xb3c86232c163a988ce4358b10a2745864bfaa3ba' +TOKEN_SENDER='0x110600bF0399174520a159ed425f0D272Ff8b459' +TOKEN_RECEIVER='0xbBa4d06D1cEf94b35aDeCfDa893523907fdD36DE' +NFT_SENDER='0xbBa4d06D1cEf94b35aDeCfDa893523907fdD36DE' +NFT_RECEIVER='0x110600bF0399174520a159ed425f0D272Ff8b459' + +ETHER_TRANSFER_TX='0x566002399664e92f82ed654c181095bdd7ff3d3f1921d963257585891f622251' +TOKEN_TRANSFER_TX='0xdabda3905e585db91768f2ef877f7fbef7c0e8612c0a09c7b379981bdbc48975' +NFT_TRANSFER_TX='0x272a4698cd2062f2463481cf9eb78b68b35d59938383679b7642e6d669ac87eb' +# Models + +# Services +# Services \ No newline at end of file diff --git a/packages/networks/evm-chains/src/models/NftTransaction.ts b/packages/networks/evm-chains/src/models/NftTransaction.ts index ebc8f27..de09fc7 100644 --- a/packages/networks/evm-chains/src/models/NftTransaction.ts +++ b/packages/networks/evm-chains/src/models/NftTransaction.ts @@ -12,7 +12,7 @@ export class NftTransaction extends ContractTransaction implements NftTransactio * @param {InterfaceAbi} ABI Contract ABI */ constructor(id: string, provider?: Provider, ABI?: InterfaceAbi) { - super(id, provider, ABI ?? ERC721) + super(id, provider, ABI ?? (ERC721 as InterfaceAbi)) } /** diff --git a/packages/networks/evm-chains/src/models/TokenTransaction.ts b/packages/networks/evm-chains/src/models/TokenTransaction.ts index b270328..da166cf 100644 --- a/packages/networks/evm-chains/src/models/TokenTransaction.ts +++ b/packages/networks/evm-chains/src/models/TokenTransaction.ts @@ -14,7 +14,7 @@ export class TokenTransaction extends ContractTransaction implements TokenTransa * @param {InterfaceAbi} ABI Contract ABI */ constructor(id: string, provider?: Provider, ABI?: InterfaceAbi) { - super(id, provider, ABI ?? ERC20) + super(id, provider, ABI ?? (ERC20 as InterfaceAbi)) } /** diff --git a/packages/networks/evm-chains/tests/assets.spec.ts b/packages/networks/evm-chains/tests/assets.spec.ts index 5b6a798..ad037d0 100644 --- a/packages/networks/evm-chains/tests/assets.spec.ts +++ b/packages/networks/evm-chains/tests/assets.spec.ts @@ -8,27 +8,29 @@ import { Transaction } from '../src/models/Transaction.ts' import { TransactionStatusEnum } from '@multiplechain/types' import { TransactionSigner } from '../src/services/TransactionSigner.ts' -const coinTransferTestIsActive = false -const tokenTransferTestIsActive = false -const tokenApproveTestIsActive = false -const tokenTransferFromTestIsActive = false -const nftTransactionTestIsActive = false - -const balanceTestAddress = '0x760A4d3D03928D1e8541A7644B34370c1b79aa9F' -const coinBalanceTestAmount = 0.01 -const tokenBalanceTestAmount = 1000 -const nftBalanceTestAmount = 2 - -const senderPrivateKey = '0x14bd9af4e87981b37b7b2e8a0d1d249b7fcdb7a3bc579c4c31488842d372c0e9' -const receiverPrivateKey = '0x22ac1009c43f251e0b5a808751990abe77a74fe12f390c0cc95ab179a0b61a5a' -const senderTestAddress = '0x110600bF0399174520a159ed425f0D272Ff8b459' -const receiverTestAddress = '0xbBa4d06D1cEf94b35aDeCfDa893523907fdD36DE' -const tokenTestAddress = '0x4294cb0dD25dC9140B5127f247cBd47Eeb673431' -const nftTestAddress = '0x06B8B36e4feD2206E980445C0f0829fc6B2aA91F' -const transferTestAmount = 0.0001 -const tokenTransferTestAmount = 1 -const tokenApproveTestAmount = 100 -const nftTransferId = 7 +const coinBalanceTestAmount = Number(process.env.COIN_BALANCE_TEST_AMOUNT) +const tokenBalanceTestAmount = Number(process.env.TOKEN_BALANCE_TEST_AMOUNT) +const nftBalanceTestAmount = Number(process.env.NFT_BALANCE_TEST_AMOUNT) +const transferTestAmount = Number(process.env.TRANSFER_TEST_AMOUNT) +const tokenTransferTestAmount = Number(process.env.TOKEN_TRANSFER_TEST_AMOUNT) +const tokenApproveTestAmount = Number(process.env.TOKEN_APPROVE_TEST_AMOUNT) +const nftTransferId = Number(process.env.NFT_TRANSFER_ID) + +const coinTransferTestIsActive = Boolean(process.env.COIN_TRANSFER_TEST_IS_ACTIVE !== 'false') +const tokenTransferTestIsActive = Boolean(process.env.TOKEN_TRANSFER_TEST_IS_ACTIVE !== 'false') +const tokenApproveTestIsActive = Boolean(process.env.TOKEN_APPROVE_TEST_IS_ACTIVE !== 'false') +const nftTransactionTestIsActive = Boolean(process.env.NFT_TRANSACTION_TEST_IS_ACTIVE !== 'false') +const tokenTransferFromTestIsActive = Boolean( + process.env.TOKEN_TRANSFER_FROM_TEST_IS_ACTIVE !== 'false' +) + +const balanceTestAddress = String(process.env.BALANCE_TEST_ADDRESS) +const senderPrivateKey = String(process.env.SENDER_PRIVATE_KEY) +const receiverPrivateKey = String(process.env.RECEIVER_PRIVATE_KEY) +const senderTestAddress = String(process.env.SENDER_TEST_ADDRESS) +const receiverTestAddress = String(process.env.RECEIVER_TEST_ADDRESS) +const tokenTestAddress = String(process.env.TOKEN_TEST_ADDRESS) +const nftTestAddress = String(process.env.NFT_TEST_ADDRESS) const waitSecondsBeforeThanNewTx = async (seconds: number): Promise => { return await new Promise((resolve) => setTimeout(resolve, seconds * 1000)) diff --git a/packages/networks/evm-chains/tests/models.spec.ts b/packages/networks/evm-chains/tests/models.spec.ts index 4b21dea..c8ce377 100644 --- a/packages/networks/evm-chains/tests/models.spec.ts +++ b/packages/networks/evm-chains/tests/models.spec.ts @@ -6,22 +6,22 @@ import { CoinTransaction } from '../src/models/CoinTransaction.ts' import { TokenTransaction } from '../src/models/TokenTransaction.ts' import { AssetDirectionEnum, TransactionStatusEnum } from '@multiplechain/types' -const etherTransferTx = '0x566002399664e92f82ed654c181095bdd7ff3d3f1921d963257585891f622251' -const tokenTransferTx = '0xdabda3905e585db91768f2ef877f7fbef7c0e8612c0a09c7b379981bdbc48975' -const nftTransferTx = '0x272a4698cd2062f2463481cf9eb78b68b35d59938383679b7642e6d669ac87eb' +const nftId = Number(process.env.NFT_ID) +const tokenAmount = Number(process.env.TOKEN_AMOUNT) +const coinAmount = Number(process.env.COIN_AMOUNT) -const nftId = 7 -const tokenAmount = 1 -const coinAmount = 0.002548 +const etherTransferTx = String(process.env.ETHER_TRANSFER_TX) +const tokenTransferTx = String(process.env.TOKEN_TRANSFER_TX) +const nftTransferTx = String(process.env.NFT_TRANSFER_TX) -const coinSender = '0x74dBE9cA4F93087A27f23164d4367b8ce66C33e2' -const coinReceiver = '0xb3C86232c163A988Ce4358B10A2745864Bfaa3Ba' +const coinSender = String(process.env.COIN_SENDER) +const coinReceiver = String(process.env.COIN_RECEIVER) -const tokenSender = '0x110600bF0399174520a159ed425f0D272Ff8b459' -const tokenReceiver = '0xbBa4d06D1cEf94b35aDeCfDa893523907fdD36DE' +const tokenSender = String(process.env.TOKEN_SENDER) +const tokenReceiver = String(process.env.TOKEN_RECEIVER) -const nftSender = '0xbBa4d06D1cEf94b35aDeCfDa893523907fdD36DE' -const nftReceiver = '0x110600bF0399174520a159ed425f0D272Ff8b459' +const nftSender = String(process.env.NFT_SENDER) +const nftReceiver = String(process.env.NFT_RECEIVER) describe('Transaction', () => { const tx = new Transaction(etherTransferTx) diff --git a/packages/networks/evm-chains/tests/setup.ts b/packages/networks/evm-chains/tests/setup.ts index 8d8014e..3f5e545 100644 --- a/packages/networks/evm-chains/tests/setup.ts +++ b/packages/networks/evm-chains/tests/setup.ts @@ -1,33 +1,16 @@ import { Provider } from '../src/services/Provider.ts' -const useCustomRpcAndWs = true - -const rpcAndWs = { - rpcUrl: 'https://sepolia.infura.io/v3/9aa3d95b3bc440fa88ea12eaa4456161', - wsUrl: 'wss://sepolia.infura.io/ws/v3/9aa3d95b3bc440fa88ea12eaa4456161' -} - -if (useCustomRpcAndWs) { - rpcAndWs.rpcUrl = - 'https://dimensional-icy-tent.ethereum-sepolia.quiknode.pro/e6a31d965b3ab5fc57d5980d187121f1894c0eb4/' - rpcAndWs.wsUrl = - 'wss://dimensional-icy-tent.ethereum-sepolia.quiknode.pro/e6a31d965b3ab5fc57d5980d187121f1894c0eb4/' -} - -export const provider = new Provider( - Object.assign( - { - id: 11155111, - hexId: '0xaa36a7', - mainnetId: 1, - name: 'Ethereum Sepolia Testnet (QR)', - explorerUrl: 'https://sepolia.etherscan.io/', - nativeCurrency: { - symbol: 'ETH', - name: 'Ethereum', - decimals: 18 - } - }, - rpcAndWs - ) -) +export const provider = new Provider({ + id: 11155111, + hexId: '0xaa36a7', + mainnetId: 1, + name: 'Ethereum Sepolia Testnet (QR)', + explorerUrl: 'https://sepolia.etherscan.io/', + rpcUrl: process.env.RPC_URL as unknown as string, + wsUrl: process.env.WS_URL as unknown as string, + nativeCurrency: { + symbol: 'ETH', + name: 'Ethereum', + decimals: 18 + } +}) diff --git a/packages/networks/evm-chains/tsconfig.json b/packages/networks/evm-chains/tsconfig.json index 7f458a3..ae078b5 100644 --- a/packages/networks/evm-chains/tsconfig.json +++ b/packages/networks/evm-chains/tsconfig.json @@ -9,12 +9,15 @@ "extends": "../../../tsconfig.json", "include": [ "src", + "cdt.ts", ".eslintrc.json", "tests", "resources/*.json", "vite.config.ts", "esbuild.ts", + "vitest.config.ts", "../../../esbuild.ts", - "../../../vite.config.ts" + "../../../vite.config.ts", + "../../../vitest.config.ts", ] } diff --git a/packages/networks/evm-chains/vitest.config.ts b/packages/networks/evm-chains/vitest.config.ts new file mode 100644 index 0000000..433e719 --- /dev/null +++ b/packages/networks/evm-chains/vitest.config.ts @@ -0,0 +1,12 @@ +import { mergeConfig, defineConfig } from 'vitest/config' +import mainConfig from '../../../vite.config.ts' + +export default mergeConfig( + mainConfig, + defineConfig({ + test: { + testTimeout: 180000, + setupFiles: ['./tests/setup.ts'] + } + }) +) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 4d5006e..bbf5a21 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -59,6 +59,9 @@ devDependencies: vite-plugin-dts: specifier: ^3.8.1 version: 3.8.1(@types/node@20.11.20)(typescript@5.3.3)(vite@5.1.4) + vite-plugin-env-compatible: + specifier: ^2.0.1 + version: 2.0.1 vite-plugin-node-polyfills: specifier: ^0.21.0 version: 0.21.0(vite@5.1.4) @@ -1682,6 +1685,15 @@ packages: engines: {node: '>=10'} dev: true + /dotenv-expand@5.1.0: + resolution: {integrity: sha512-YXQl1DSa4/PQyRfgrv6aoNjhasp/p4qs9FjJ4q4cQk+8m4r6k4ZSiEyytKG8f8W9gi8WsQtIObNmKd+tMzNTmA==} + dev: true + + /dotenv@8.2.0: + resolution: {integrity: sha512-8sJ78ElpbDJBHNeBzUbUVLsqKdccaa/BXF1uPTw3GrvQTBgrQrtObr2mUrE38vzYd8cEv+m/JBfDLioYcfXoaw==} + engines: {node: '>=8'} + dev: true + /elliptic@6.5.4: resolution: {integrity: sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ==} dependencies: @@ -4016,6 +4028,13 @@ packages: - supports-color dev: true + /vite-plugin-env-compatible@2.0.1: + resolution: {integrity: sha512-DRrOZTg/W44ojVQQfGSMPEgYQGzp5TeIpt9cpaK35hTOC/b2D7Ffl8/RIgK8vQ0mlnDIUgETcA173bnMEkyzdw==} + dependencies: + dotenv: 8.2.0 + dotenv-expand: 5.1.0 + dev: true + /vite-plugin-node-polyfills@0.21.0(vite@5.1.4): resolution: {integrity: sha512-Sk4DiKnmxN8E0vhgEhzLudfJQfaT8k4/gJ25xvUPG54KjLJ6HAmDKbr4rzDD/QWEY+Lwg80KE85fGYBQihEPQA==} peerDependencies: diff --git a/vite.config.ts b/vite.config.ts index a20fb22..ce9b83c 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -1,11 +1,13 @@ import { defineConfig } from 'vite' import dts from 'vite-plugin-dts' +import envCompatible from 'vite-plugin-env-compatible' export default defineConfig({ plugins: [ dts({ entryRoot: './src' - }) + }), + envCompatible() ], build: { minify: true, diff --git a/vitest.config.ts b/vitest.config.ts index 817263e..208af65 100644 --- a/vitest.config.ts +++ b/vitest.config.ts @@ -9,8 +9,7 @@ export default mergeConfig( testTimeout: 180000, environment: 'jsdom', exclude: [...configDefaults.exclude, 'e2e/*'], - root: fileURLToPath(new URL('./', import.meta.url)), - setupFiles: ['./packages/networks/evm-chains/tests/setup.ts'] + root: fileURLToPath(new URL('./', import.meta.url)) } }) ) From 9876ff9203e1132d058980125245bbafac5097df Mon Sep 17 00:00:00 2001 From: Halil Beycan <50718965+BeycanDeveloper@users.noreply.github.com> Date: Fri, 5 Apr 2024 22:56:43 +0800 Subject: [PATCH 108/114] updated checkWebSocket reject --- packages/utils/package.json | 2 +- packages/utils/src/index.ts | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/packages/utils/package.json b/packages/utils/package.json index 65cd08d..54b9a49 100644 --- a/packages/utils/package.json +++ b/packages/utils/package.json @@ -1,6 +1,6 @@ { "name": "@multiplechain/utils", - "version": "0.1.15", + "version": "0.1.16", "type": "module", "main": "./src/index.ts", "types": "./src/index.ts", diff --git a/packages/utils/src/index.ts b/packages/utils/src/index.ts index bc48034..8da26e5 100644 --- a/packages/utils/src/index.ts +++ b/packages/utils/src/index.ts @@ -128,20 +128,20 @@ export const sleep = async (ms: number): Promise => { /** * Checks if the given objects are equal - * @param {any} o1 - * @param {any} o2 + * @param {object} o1 + * @param {object} o2 * @returns boolean */ -export const objectsEqual = (o1: any, o2: any): boolean => { +export const objectsEqual = (o1: object, o2: object): boolean => { return JSON.stringify(o1) === JSON.stringify(o2) } /** * checks if the given url is a valid websocket url * @param {string} url - * @returns {Promise} + * @returns {Promise} */ -export const checkWebSocket = async (url: string): Promise => { +export const checkWebSocket = async (url: string): Promise => { return await new Promise((resolve, reject) => { let socket: WebSocket | NodeWebSocket @@ -157,7 +157,7 @@ export const checkWebSocket = async (url: string): Promise => } socket.onerror = (error: ErrorEvent) => { - reject(error.message) + reject(new Error(error.message)) socket.close() } }) From b842023dfba0c0dea2191ea9ad68b39acb66da92 Mon Sep 17 00:00:00 2001 From: Halil Beycan <50718965+BeycanDeveloper@users.noreply.github.com> Date: Fri, 5 Apr 2024 23:42:20 +0800 Subject: [PATCH 109/114] services tests done --- packages/networks/evm-chains/.env.example | 4 +- packages/networks/evm-chains/package.json | 2 +- packages/networks/evm-chains/pnpm-lock.yaml | 8 +- packages/networks/evm-chains/src/index.ts | 1 + .../src/models/ContractTransaction.ts | 5 +- .../evm-chains/src/services/Ethers.ts | 8 +- .../evm-chains/src/services/Provider.ts | 8 +- .../evm-chains/tests/services.spec.ts | 185 +++++++++++++++++- packages/networks/evm-chains/tests/setup.ts | 37 ++-- 9 files changed, 224 insertions(+), 34 deletions(-) diff --git a/packages/networks/evm-chains/.env.example b/packages/networks/evm-chains/.env.example index 618e685..e2ef720 100644 --- a/packages/networks/evm-chains/.env.example +++ b/packages/networks/evm-chains/.env.example @@ -1,15 +1,13 @@ RPC_URL='https://sepolia.infura.io/v3/9aa3d95b3bc440fa88ea12eaa4456161' WS_URL='wss://sepolia.infura.io/ws/v3/9aa3d95b3bc440fa88ea12eaa4456161' -BACKUP_RPC_URL='https://dimensional-icy-tent.ethereum-sepolia.quiknode.pro/e6a31d965b3ab5fc57d5980d187121f1894c0eb4/' -BACKUP_WS_URL='wss://dimensional-icy-tent.ethereum-sepolia.quiknode.pro/ws/e6a31d965b3ab5fc57d5980d187121f1894c0eb4/' - # Assets COIN_TRANSFER_TEST_IS_ACTIVE=true TOKEN_TRANSFER_TEST_IS_ACTIVE=false TOKEN_APPROVE_TEST_IS_ACTIVE=false TOKEN_TRANSFER_FROM_TEST_IS_ACTIVE=false NFT_TRANSACTION_TEST_IS_ACTIVE=false +TRANSACTION_LISTENER_TEST_IS_ACTIVE=false COIN_BALANCE_TEST_AMOUNT=0.01 TOKEN_BALANCE_TEST_AMOUNT=1000 diff --git a/packages/networks/evm-chains/package.json b/packages/networks/evm-chains/package.json index 90d1a1e..7d7c87b 100644 --- a/packages/networks/evm-chains/package.json +++ b/packages/networks/evm-chains/package.json @@ -51,7 +51,7 @@ }, "dependencies": { "@multiplechain/types": "^0.1.35", - "@multiplechain/utils": "^0.1.15", + "@multiplechain/utils": "^0.1.16", "@wagmi/chains": "^1.8.0", "ethers": "^6.11.1" } diff --git a/packages/networks/evm-chains/pnpm-lock.yaml b/packages/networks/evm-chains/pnpm-lock.yaml index 0ba8652..63086cb 100644 --- a/packages/networks/evm-chains/pnpm-lock.yaml +++ b/packages/networks/evm-chains/pnpm-lock.yaml @@ -9,8 +9,8 @@ dependencies: specifier: ^0.1.35 version: 0.1.35 '@multiplechain/utils': - specifier: ^0.1.15 - version: 0.1.15 + specifier: ^0.1.16 + version: 0.1.16 '@wagmi/chains': specifier: ^1.8.0 version: 1.8.0 @@ -28,8 +28,8 @@ packages: resolution: {integrity: sha512-szg+arayBvT3WivUa9l6ZYjS6tNjhFMDpQCcAUL94s5yWpDM73OnHMA861XVVVY0xIUgJpzCj32PlJU+CARYow==} dev: false - /@multiplechain/utils@0.1.15: - resolution: {integrity: sha512-52jI4QAR3zNvk59TDvZ93xWNp96Vnx6fqXd4/XaVWcfITHwKJgfupnk/QqwaZsJ0a4IPxyz5AVtZ3pESwL7X+Q==} + /@multiplechain/utils@0.1.16: + resolution: {integrity: sha512-wJPLuHRt2r8DZt0S6YkeRZRRcy/bc20/Y0xolESOIWfLdBy/N5YKBMJaAwEV+pOWuP77Mx+rzZBlfeOBmvZBXw==} dependencies: '@types/ws': 8.5.10 bignumber.js: 9.1.2 diff --git a/packages/networks/evm-chains/src/index.ts b/packages/networks/evm-chains/src/index.ts index f174cc8..b06e38c 100644 --- a/packages/networks/evm-chains/src/index.ts +++ b/packages/networks/evm-chains/src/index.ts @@ -4,5 +4,6 @@ export * as assets from './assets/index.ts' export * as models from './models/index.ts' export * as services from './services/index.ts' export { default as networks } from './services/Networks.ts' + export * as utils from '@multiplechain/utils' export * as types from '@multiplechain/types' diff --git a/packages/networks/evm-chains/src/models/ContractTransaction.ts b/packages/networks/evm-chains/src/models/ContractTransaction.ts index 6878378..2a097c5 100644 --- a/packages/networks/evm-chains/src/models/ContractTransaction.ts +++ b/packages/networks/evm-chains/src/models/ContractTransaction.ts @@ -8,7 +8,10 @@ import { } from 'ethers' import type { Provider } from '../services/Provider.ts' -export class ContractTransaction extends Transaction implements ContractTransactionInterface { +export abstract class ContractTransaction + extends Transaction + implements ContractTransactionInterface +{ /** * @type {InterfaceAbi} */ diff --git a/packages/networks/evm-chains/src/services/Ethers.ts b/packages/networks/evm-chains/src/services/Ethers.ts index 4ad5180..aa3b97c 100644 --- a/packages/networks/evm-chains/src/services/Ethers.ts +++ b/packages/networks/evm-chains/src/services/Ethers.ts @@ -62,11 +62,11 @@ export class Ethers { } else { const url = this.network.wsUrl checkWebSocket(url) - .then((status) => { - if (status === true) { - resolve((this.webSocketProvider = new WebSocketProvider(url))) + .then((status: any) => { + if (status instanceof Error) { + reject(status) } else { - reject(new Error('WebSocket is not available')) + resolve((this.webSocketProvider = new WebSocketProvider(url))) } }) .catch(reject) diff --git a/packages/networks/evm-chains/src/services/Provider.ts b/packages/networks/evm-chains/src/services/Provider.ts index 81204ba..ede4232 100644 --- a/packages/networks/evm-chains/src/services/Provider.ts +++ b/packages/networks/evm-chains/src/services/Provider.ts @@ -106,13 +106,13 @@ export class Provider implements Omit { */ async checkWsConnection(url?: string): Promise { try { - const result = await checkWebSocket(url ?? this.network.rpcUrl) + const result: any = await checkWebSocket(url ?? this.network.rpcUrl) - if (result === true) { - return true + if (result instanceof Error) { + return result } - return new Error(result as string) + return true } catch (error) { return error as Error } diff --git a/packages/networks/evm-chains/tests/services.spec.ts b/packages/networks/evm-chains/tests/services.spec.ts index e2ec6b3..ec39494 100644 --- a/packages/networks/evm-chains/tests/services.spec.ts +++ b/packages/networks/evm-chains/tests/services.spec.ts @@ -1,7 +1,186 @@ import { describe, it, expect } from 'vitest' -describe('Tests for services', () => { - it('should load services', async () => { - expect(1).toBe(1) +import { provider } from './setup.ts' +import { Provider } from '../src/services/Provider.ts' +import { TransactionListener } from '../src/services/TransactionListener.ts' +import { TransactionTypeEnum } from '@multiplechain/types' +import { Coin } from '../src/assets/Coin.ts' +import { CoinTransaction } from '../src/models/CoinTransaction.ts' +import { ContractTransaction } from '../src/models/ContractTransaction.ts' +import { Token } from '../src/assets/Token.ts' +import { Transaction } from '../src/models/Transaction.ts' +import { TokenTransaction } from '../src/models/TokenTransaction.ts' +import { NftTransaction } from '../src/models/NftTransaction.ts' +import { NFT } from '../src/assets/NFT.ts' + +const senderPrivateKey = String(process.env.SENDER_PRIVATE_KEY) +const receiverPrivateKey = String(process.env.RECEIVER_PRIVATE_KEY) +const senderTestAddress = String(process.env.SENDER_TEST_ADDRESS) +const receiverTestAddress = String(process.env.RECEIVER_TEST_ADDRESS) +const tokenTestAddress = String(process.env.TOKEN_TEST_ADDRESS) +const nftTestAddress = String(process.env.NFT_TEST_ADDRESS) + +const transactionListenerTestIsActive = Boolean( + process.env.TRANSACTION_LISTENER_TEST_IS_ACTIVE !== 'false' +) + +const waitSecondsBeforeThanNewTx = async (seconds: number): Promise => { + return await new Promise((resolve) => setTimeout(resolve, seconds * 1000)) +} + +describe('Provider', () => { + it('isTestnet', () => { + expect(provider.isTestnet()).toBe(true) + }) + + it('instance', () => { + expect(Provider.instance).toBe(provider) + }) + + it('checkRpcConnection', async () => { + expect(await provider.checkRpcConnection('https://sepolia.infura.io/v3')).instanceOf(Error) + expect(await provider.checkRpcConnection(process.env.RPC_URL as unknown as string)).toBe( + true + ) + }) + + it('checkWsConnection', async () => { + expect(await provider.checkWsConnection('wss://sepolia.infura.io/v3')).instanceOf(Error) + expect(await provider.checkWsConnection(process.env.WS_URL as unknown as string)).toBe(true) + }) +}) + +describe('Transaction Listener', () => { + if (!transactionListenerTestIsActive) { + it('No test is active', () => { + expect(true).toBe(true) + }) + return + } + + it('General', async () => { + const listener = new TransactionListener(TransactionTypeEnum.GENERAL, provider, { + signer: senderTestAddress + }) + + void listener.on((transaction) => { + listener.stop() + expect(transaction).toBeInstanceOf(Transaction) + }) + + const signer = await new Coin().transfer(senderTestAddress, receiverTestAddress, 0.0001) + + const transaction = await (await signer.sign(senderPrivateKey)).send() + + expect(transaction).toBeInstanceOf(Transaction) + + void (await transaction.wait()) + }) + + it('Contract', async () => { + await waitSecondsBeforeThanNewTx(10) + + const listener = new TransactionListener(TransactionTypeEnum.CONTRACT, provider, { + signer: senderTestAddress, + address: tokenTestAddress + }) + + void listener.on((transaction) => { + listener.stop() + expect(transaction).toBeInstanceOf(ContractTransaction) + }) + + const signer = await new Token(tokenTestAddress).transfer( + senderTestAddress, + receiverTestAddress, + 0.01 + ) + + const transaction = await (await signer.sign(senderPrivateKey)).send() + + expect(transaction).toBeInstanceOf(ContractTransaction) + + void (await transaction.wait()) + }) + + it('Coin', async () => { + await waitSecondsBeforeThanNewTx(10) + + const listener = new TransactionListener(TransactionTypeEnum.COIN, provider, { + signer: senderTestAddress, + receiver: receiverTestAddress + }) + + void listener.on((transaction) => { + listener.stop() + expect(transaction).toBeInstanceOf(CoinTransaction) + }) + + const signer = await new Coin().transfer(senderTestAddress, receiverTestAddress, 0.0001) + + const transaction = await (await signer.sign(senderPrivateKey)).send() + + expect(transaction).toBeInstanceOf(CoinTransaction) + + void (await transaction.wait()) + }) + + it('Token', async () => { + await waitSecondsBeforeThanNewTx(10) + + const listener = new TransactionListener(TransactionTypeEnum.TOKEN, provider, { + signer: senderTestAddress, + receiver: receiverTestAddress, + address: tokenTestAddress + }) + + void listener.on((transaction) => { + listener.stop() + expect(transaction).toBeInstanceOf(TokenTransaction) + }) + + const signer = await new Token(tokenTestAddress).transfer( + senderTestAddress, + receiverTestAddress, + 0.01 + ) + + const transaction = await (await signer.sign(senderPrivateKey)).send() + + expect(transaction).toBeInstanceOf(TokenTransaction) + + void (await transaction.wait()) + }) + + it('NFT', async () => { + await waitSecondsBeforeThanNewTx(10) + + const listener = new TransactionListener(TransactionTypeEnum.NFT, provider, { + signer: senderTestAddress, + receiver: receiverTestAddress, + address: nftTestAddress + }) + + void listener.on((transaction) => { + listener.stop() + expect(transaction).toBeInstanceOf(NftTransaction) + }) + + const nft = new NFT(nftTestAddress) + const signer = await nft.transfer(senderTestAddress, receiverTestAddress, 9) + + const transaction = await (await signer.sign(senderPrivateKey)).send() + + expect(transaction).toBeInstanceOf(NftTransaction) + + void (await transaction.wait()) + + await waitSecondsBeforeThanNewTx(10) + + const newSigner = await nft.transfer(receiverTestAddress, senderTestAddress, 9) + + const newTransaction = await (await newSigner.sign(receiverPrivateKey)).send() + + expect(newTransaction).toBeInstanceOf(NftTransaction) }) }) diff --git a/packages/networks/evm-chains/tests/setup.ts b/packages/networks/evm-chains/tests/setup.ts index 3f5e545..0257953 100644 --- a/packages/networks/evm-chains/tests/setup.ts +++ b/packages/networks/evm-chains/tests/setup.ts @@ -1,16 +1,25 @@ import { Provider } from '../src/services/Provider.ts' -export const provider = new Provider({ - id: 11155111, - hexId: '0xaa36a7', - mainnetId: 1, - name: 'Ethereum Sepolia Testnet (QR)', - explorerUrl: 'https://sepolia.etherscan.io/', - rpcUrl: process.env.RPC_URL as unknown as string, - wsUrl: process.env.WS_URL as unknown as string, - nativeCurrency: { - symbol: 'ETH', - name: 'Ethereum', - decimals: 18 - } -}) +let provider: Provider + +try { + provider = Provider.instance +} catch (e) { + provider = new Provider({ + id: 11155111, + hexId: '0xaa36a7', + mainnetId: 1, + testnet: true, + name: 'Ethereum Sepolia Testnet (QR)', + explorerUrl: 'https://sepolia.etherscan.io/', + rpcUrl: process.env.RPC_URL as unknown as string, + wsUrl: process.env.WS_URL as unknown as string, + nativeCurrency: { + symbol: 'ETH', + name: 'Ethereum', + decimals: 18 + } + }) +} + +export { provider } From 71af5ff7942998e5bd97e4a708b9e7e09d63a014 Mon Sep 17 00:00:00 2001 From: Halil Beycan <50718965+BeycanDeveloper@users.noreply.github.com> Date: Fri, 5 Apr 2024 23:42:34 +0800 Subject: [PATCH 110/114] updated --- packages/networks/boilerplate/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/networks/boilerplate/package.json b/packages/networks/boilerplate/package.json index eb481d0..7a27d29 100644 --- a/packages/networks/boilerplate/package.json +++ b/packages/networks/boilerplate/package.json @@ -48,6 +48,6 @@ }, "dependencies": { "@multiplechain/types": "^0.1.35", - "@multiplechain/utils": "^0.1.15" + "@multiplechain/utils": "^0.1.16" } } \ No newline at end of file From 56d83a5c4de0cd1e645a7466989b58e497194f50 Mon Sep 17 00:00:00 2001 From: Halil Beycan <50718965+BeycanDeveloper@users.noreply.github.com> Date: Fri, 5 Apr 2024 23:44:49 +0800 Subject: [PATCH 111/114] removed abstract --- packages/networks/evm-chains/package.json | 2 +- .../networks/evm-chains/src/models/ContractTransaction.ts | 5 +---- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/packages/networks/evm-chains/package.json b/packages/networks/evm-chains/package.json index 7d7c87b..12d4884 100644 --- a/packages/networks/evm-chains/package.json +++ b/packages/networks/evm-chains/package.json @@ -1,6 +1,6 @@ { "name": "@multiplechain/evm-chains", - "version": "0.3.36", + "version": "0.3.37", "type": "module", "types": "dist/index.d.ts", "main": "dist/index.cjs", diff --git a/packages/networks/evm-chains/src/models/ContractTransaction.ts b/packages/networks/evm-chains/src/models/ContractTransaction.ts index 2a097c5..6878378 100644 --- a/packages/networks/evm-chains/src/models/ContractTransaction.ts +++ b/packages/networks/evm-chains/src/models/ContractTransaction.ts @@ -8,10 +8,7 @@ import { } from 'ethers' import type { Provider } from '../services/Provider.ts' -export abstract class ContractTransaction - extends Transaction - implements ContractTransactionInterface -{ +export class ContractTransaction extends Transaction implements ContractTransactionInterface { /** * @type {InterfaceAbi} */ From c8fab44a1a32895fd8a6cd48143436dfce0789b6 Mon Sep 17 00:00:00 2001 From: Halil Beycan <50718965+BeycanDeveloper@users.noreply.github.com> Date: Sat, 6 Apr 2024 01:17:33 +0800 Subject: [PATCH 112/114] created auto publish workflow --- .github/workflows/npm-publish.yaml | 48 +++++++++++++++++++++++ packages/networks/evm-chains/package.json | 2 +- 2 files changed, 49 insertions(+), 1 deletion(-) create mode 100644 .github/workflows/npm-publish.yaml diff --git a/.github/workflows/npm-publish.yaml b/.github/workflows/npm-publish.yaml new file mode 100644 index 0000000..538a670 --- /dev/null +++ b/.github/workflows/npm-publish.yaml @@ -0,0 +1,48 @@ +name: NPM Auto Publish + +on: + release: + types: + - released + branches: + - master + +jobs: + check-packages: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + + - name: Set up Node.js + uses: actions/setup-node@v4 + with: + node-version: '20' + + - name: Login to npm registry + run: npm config set //registry.npmjs.org/:_authToken=$NPM_AUTH_TOKEN + env: + NPM_AUTH_TOKEN: ${{secrets.NPM_AUTH_TOKEN}} + + - name: Check if version changed + run: | + npm install -g pnpm + + for dir in packages/*/ packages/networks/*/; do + if [ -d "$dir" ] && [ "$(basename "$dir")" != "boilerplate" ]; then + cd "$dir" || exit + + PACKAGE_INFO=$(node -p "JSON.stringify(require('./package.json'))") + PACKAGE_NAME=$(echo "$PACKAGE_INFO" | jq -r '.name') + CURRENT_VERSION=$(echo "$PACKAGE_INFO" | jq -r '.version') + + PREVIOUS_VERSION=$(npm show "$PACKAGE_NAME" version) + + if [ "$PREVIOUS_VERSION" != "$CURRENT_VERSION" ]; then + echo "Version changed for $PACKAGE_NAME from $PREVIOUS_VERSION to $CURRENT_VERSION" + pnpm install && npm publish + fi + + cd - || exit + fi + done \ No newline at end of file diff --git a/packages/networks/evm-chains/package.json b/packages/networks/evm-chains/package.json index 12d4884..fd6be2e 100644 --- a/packages/networks/evm-chains/package.json +++ b/packages/networks/evm-chains/package.json @@ -1,6 +1,6 @@ { "name": "@multiplechain/evm-chains", - "version": "0.3.37", + "version": "0.3.38", "type": "module", "types": "dist/index.d.ts", "main": "dist/index.cjs", From c31739818e2e4032dd4411fc1ddc3678bc6c43be Mon Sep 17 00:00:00 2001 From: Halil Beycan <50718965+BeycanDeveloper@users.noreply.github.com> Date: Sat, 6 Apr 2024 02:36:18 +0800 Subject: [PATCH 113/114] lint and test --- .../evm-chains/.env.example => .env.example | 7 ++- .github/workflows/test-and-lint.yaml | 49 +++++++++++++++++++ package.json | 4 -- vitest.config.ts | 4 +- 4 files changed, 55 insertions(+), 9 deletions(-) rename packages/networks/evm-chains/.env.example => .env.example (96%) create mode 100644 .github/workflows/test-and-lint.yaml diff --git a/packages/networks/evm-chains/.env.example b/.env.example similarity index 96% rename from packages/networks/evm-chains/.env.example rename to .env.example index e2ef720..299ce21 100644 --- a/packages/networks/evm-chains/.env.example +++ b/.env.example @@ -1,8 +1,9 @@ +# EVM CHAINS RPC_URL='https://sepolia.infura.io/v3/9aa3d95b3bc440fa88ea12eaa4456161' WS_URL='wss://sepolia.infura.io/ws/v3/9aa3d95b3bc440fa88ea12eaa4456161' # Assets -COIN_TRANSFER_TEST_IS_ACTIVE=true +COIN_TRANSFER_TEST_IS_ACTIVE=false TOKEN_TRANSFER_TEST_IS_ACTIVE=false TOKEN_APPROVE_TEST_IS_ACTIVE=false TOKEN_TRANSFER_FROM_TEST_IS_ACTIVE=false @@ -42,6 +43,4 @@ ETHER_TRANSFER_TX='0x566002399664e92f82ed654c181095bdd7ff3d3f1921d963257585891f6 TOKEN_TRANSFER_TX='0xdabda3905e585db91768f2ef877f7fbef7c0e8612c0a09c7b379981bdbc48975' NFT_TRANSFER_TX='0x272a4698cd2062f2463481cf9eb78b68b35d59938383679b7642e6d669ac87eb' # Models - -# Services -# Services \ No newline at end of file +# EVM CHAINS \ No newline at end of file diff --git a/.github/workflows/test-and-lint.yaml b/.github/workflows/test-and-lint.yaml new file mode 100644 index 0000000..3270b9d --- /dev/null +++ b/.github/workflows/test-and-lint.yaml @@ -0,0 +1,49 @@ +name: Test and Lint Check + +on: + pull_request: + types: [opened, synchronize, reopened, edited] + branches: + - alpha + - master + +jobs: + test_and_lint: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + + - name: Set up Node.js + uses: actions/setup-node@v4 + with: + node-version: '20' + + - name: Create .env file + run: cp .env.example .env + + - name: Install dependencies + run: | + npm install -g pnpm + + for dir in packages/*/ packages/networks/*/; do + if [ -d "$dir" ] && [ "$(basename "$dir")" != "boilerplate" ]; then + cd "$dir" || exit + pnpm install + cd - || exit + fi + done + + - name: Run test + run: npm run test + + - name: Runt lint + run: npm run lint + + - name: Set PR status + if: ${{ github.event_name == 'pull_request' }} + run: | + TOKEN="${{ secrets.GITHUB_TOKEN }}" + STATUS_URL="https://api.github.com/repos/${GITHUB_REPOSITORY}/statuses/${GITHUB_SHA}" + STATUS="{\"state\":\"success\",\"context\":\"Test Process\",\"description\":\"Test Process passed\"}" + curl -X POST -H "Authorization: token $TOKEN" -d "$STATUS" "$STATUS_URL" diff --git a/package.json b/package.json index 708c919..7412014 100644 --- a/package.json +++ b/package.json @@ -3,10 +3,6 @@ "version": "0.0.0", "type": "module", "scripts": { - "dev": "vite", - "build": "tsc && vite build", - "preview": "vite preview", - "build:watch": "vite build --watch", "test": "vitest", "format": "prettier --write packages/", "lint": "eslint . --ext .ts --ignore-path .gitignore" diff --git a/vitest.config.ts b/vitest.config.ts index 208af65..02f5bf0 100644 --- a/vitest.config.ts +++ b/vitest.config.ts @@ -6,8 +6,10 @@ export default mergeConfig( viteConfig, defineConfig({ test: { + watch: false, testTimeout: 180000, - environment: 'jsdom', + environment: 'node', + setupFiles: ['./packages/networks/evm-chains/tests/setup.ts'], exclude: [...configDefaults.exclude, 'e2e/*'], root: fileURLToPath(new URL('./', import.meta.url)) } From 84788a063dc2e767f4efa8e4d336f95520d819dd Mon Sep 17 00:00:00 2001 From: Halil Beycan <50718965+BeycanDeveloper@users.noreply.github.com> Date: Sat, 6 Apr 2024 09:28:15 +0800 Subject: [PATCH 114/114] ignored boilerplate folder --- .eslintrc.json | 8 +++++++- .../boilerplate/src/services/Provider.ts | 18 ++++++++++++++++++ 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/.eslintrc.json b/.eslintrc.json index e406f00..4fa3012 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -25,5 +25,11 @@ "rules": { "filenames/match-exported": ["error", "pascal"] }, - "ignorePatterns": ["**/*.d.ts", "dist/", "node_modules/", "test*.ts"] + "ignorePatterns": [ + "**/*.d.ts", + "dist/", + "node_modules/", + "test*.ts", + "packages/networks/boilerplate/" + ] } diff --git a/packages/networks/boilerplate/src/services/Provider.ts b/packages/networks/boilerplate/src/services/Provider.ts index 9323774..9377756 100644 --- a/packages/networks/boilerplate/src/services/Provider.ts +++ b/packages/networks/boilerplate/src/services/Provider.ts @@ -45,6 +45,24 @@ export class Provider implements ProviderInterface { Provider._instance = new Provider(network) } + /** + * Check RPC connection + * @param {string} url - RPC URL + * @returns {Promise} + */ + async checkRpcConnection(url?: string): Promise { + return true + } + + /** + * Check WS connection + * @param {string} url - Websocket URL + * @returns {Promise} + */ + async checkWsConnection(url?: string): Promise { + return true + } + /** * Update network configuration of the provider * @param network - Network configuration of the provider