From 72f5859a30d4a42d07a897bde927119067902f73 Mon Sep 17 00:00:00 2001 From: rustin01 <141540002+rustin01@users.noreply.github.com> Date: Mon, 16 Dec 2024 21:45:07 +0800 Subject: [PATCH] Feat/add chain wallet sdks (#219) --- package.json | 5 + packages/coin-base/.gitignore | 24 + packages/coin-base/.prettierignore | 1 + packages/coin-base/package.json | 47 + packages/coin-base/src/enums.ts | 20 + packages/coin-base/src/index.ts | 22 + packages/coin-base/src/types.ts | 251 +++++ packages/coin-base/src/vite-env.d.ts | 1 + packages/coin-base/tsconfig.json | 12 + packages/coin-base/vite.config.ts | 38 + packages/coin-dfinity/.gitignore | 24 + packages/coin-dfinity/.prettierignore | 1 + packages/coin-dfinity/package.json | 56 ++ .../coin-dfinity/src/chain-wallet/chain.ts | 29 + .../coin-dfinity/src/chain-wallet/index.ts | 4 + .../coin-dfinity/src/chain-wallet/types.ts | 144 +++ .../coin-dfinity/src/chain-wallet/utils.ts | 105 ++ .../src/chain-wallet/wallet.test.ts | 50 + .../coin-dfinity/src/chain-wallet/wallet.ts | 231 +++++ packages/coin-dfinity/src/index.ts | 1 + packages/coin-dfinity/src/vite-env.d.ts | 1 + packages/coin-dfinity/tsconfig.json | 12 + packages/coin-dfinity/vite.config.ts | 38 + packages/coin-ethereum/.gitignore | 24 + packages/coin-ethereum/.prettierignore | 1 + packages/coin-ethereum/package.json | 47 + .../coin-ethereum/src/chain-wallet/chain.ts | 204 ++++ .../coin-ethereum/src/chain-wallet/index.ts | 2 + .../coin-ethereum/src/chain-wallet/utils.ts | 24 + .../coin-ethereum/src/chain-wallet/wallet.ts | 140 +++ packages/coin-ethereum/src/index.ts | 1 + packages/coin-ethereum/src/vite-env.d.ts | 1 + packages/coin-ethereum/tsconfig.json | 12 + packages/coin-ethereum/vite.config.ts | 38 + packages/coin-kaspa/package.json | 4 +- packages/coin-kaspa/src/chain-wallet/chain.ts | 54 + packages/coin-kaspa/src/chain-wallet/index.ts | 2 + packages/coin-kaspa/src/chain-wallet/utils.ts | 38 + .../coin-kaspa/src/chain-wallet/wallet.ts | 305 ++++++ packages/coin-kaspa/src/index.ts | 1 + packages/coin-kaspa/src/lib/index.ts | 2 +- packages/coin-kaspa/src/lib/send-param.ts | 8 +- .../coin-kaspa/tests/tx/generator-kas.test.ts | 8 +- .../tests/tx/generator-krc20.test.ts | 4 +- packages/coin-solana/.gitignore | 24 + packages/coin-solana/.prettierignore | 1 + packages/coin-solana/package.json | 47 + .../coin-solana/src/chain-wallet/chain.ts | 33 + .../coin-solana/src/chain-wallet/index.ts | 2 + .../coin-solana/src/chain-wallet/wallet.ts | 0 packages/coin-solana/src/index.ts | 1 + packages/coin-solana/src/vite-env.d.ts | 1 + packages/coin-solana/tsconfig.json | 12 + packages/coin-solana/vite.config.ts | 38 + packages/coin-ton/.gitignore | 24 + packages/coin-ton/.prettierignore | 1 + packages/coin-ton/package.json | 54 + packages/coin-ton/src/chain-wallet/chain.ts | 116 +++ packages/coin-ton/src/chain-wallet/index.ts | 2 + packages/coin-ton/src/chain-wallet/utils.ts | 12 + packages/coin-ton/src/chain-wallet/wallet.ts | 338 +++++++ packages/coin-ton/src/index.ts | 2 + packages/coin-ton/src/ton-connect/index.ts | 1 + packages/coin-ton/src/ton-connect/types.ts | 46 + packages/coin-ton/src/vite-env.d.ts | 1 + packages/coin-ton/tsconfig.json | 12 + packages/coin-ton/vite.config.ts | 38 + packages/coin-tron/.gitignore | 24 + packages/coin-tron/.prettierignore | 1 + packages/coin-tron/package.json | 46 + packages/coin-tron/src/chain-wallet/chain.ts | 86 ++ packages/coin-tron/src/chain-wallet/index.ts | 2 + packages/coin-tron/src/chain-wallet/wallet.ts | 0 packages/coin-tron/src/index.ts | 1 + packages/coin-tron/src/vite-env.d.ts | 1 + packages/coin-tron/tsconfig.json | 12 + packages/coin-tron/vite.config.ts | 38 + packages/crypto-lib/package.json | 8 +- packages/sdk/README.md | 6 +- packages/sdk/src/lib/index.ts | 3 + turbo.json | 54 +- yarn.lock | 941 +++++++++++++++++- 82 files changed, 4006 insertions(+), 60 deletions(-) create mode 100644 packages/coin-base/.gitignore create mode 100644 packages/coin-base/.prettierignore create mode 100644 packages/coin-base/package.json create mode 100644 packages/coin-base/src/enums.ts create mode 100644 packages/coin-base/src/index.ts create mode 100644 packages/coin-base/src/types.ts create mode 100644 packages/coin-base/src/vite-env.d.ts create mode 100644 packages/coin-base/tsconfig.json create mode 100644 packages/coin-base/vite.config.ts create mode 100644 packages/coin-dfinity/.gitignore create mode 100644 packages/coin-dfinity/.prettierignore create mode 100644 packages/coin-dfinity/package.json create mode 100644 packages/coin-dfinity/src/chain-wallet/chain.ts create mode 100644 packages/coin-dfinity/src/chain-wallet/index.ts create mode 100644 packages/coin-dfinity/src/chain-wallet/types.ts create mode 100644 packages/coin-dfinity/src/chain-wallet/utils.ts create mode 100644 packages/coin-dfinity/src/chain-wallet/wallet.test.ts create mode 100644 packages/coin-dfinity/src/chain-wallet/wallet.ts create mode 100644 packages/coin-dfinity/src/index.ts create mode 100644 packages/coin-dfinity/src/vite-env.d.ts create mode 100644 packages/coin-dfinity/tsconfig.json create mode 100644 packages/coin-dfinity/vite.config.ts create mode 100644 packages/coin-ethereum/.gitignore create mode 100644 packages/coin-ethereum/.prettierignore create mode 100644 packages/coin-ethereum/package.json create mode 100644 packages/coin-ethereum/src/chain-wallet/chain.ts create mode 100644 packages/coin-ethereum/src/chain-wallet/index.ts create mode 100644 packages/coin-ethereum/src/chain-wallet/utils.ts create mode 100644 packages/coin-ethereum/src/chain-wallet/wallet.ts create mode 100644 packages/coin-ethereum/src/index.ts create mode 100644 packages/coin-ethereum/src/vite-env.d.ts create mode 100644 packages/coin-ethereum/tsconfig.json create mode 100644 packages/coin-ethereum/vite.config.ts create mode 100644 packages/coin-kaspa/src/chain-wallet/chain.ts create mode 100644 packages/coin-kaspa/src/chain-wallet/index.ts create mode 100644 packages/coin-kaspa/src/chain-wallet/utils.ts create mode 100644 packages/coin-kaspa/src/chain-wallet/wallet.ts create mode 100644 packages/coin-solana/.gitignore create mode 100644 packages/coin-solana/.prettierignore create mode 100644 packages/coin-solana/package.json create mode 100644 packages/coin-solana/src/chain-wallet/chain.ts create mode 100644 packages/coin-solana/src/chain-wallet/index.ts create mode 100644 packages/coin-solana/src/chain-wallet/wallet.ts create mode 100644 packages/coin-solana/src/index.ts create mode 100644 packages/coin-solana/src/vite-env.d.ts create mode 100644 packages/coin-solana/tsconfig.json create mode 100644 packages/coin-solana/vite.config.ts create mode 100644 packages/coin-ton/.gitignore create mode 100644 packages/coin-ton/.prettierignore create mode 100644 packages/coin-ton/package.json create mode 100644 packages/coin-ton/src/chain-wallet/chain.ts create mode 100644 packages/coin-ton/src/chain-wallet/index.ts create mode 100644 packages/coin-ton/src/chain-wallet/utils.ts create mode 100644 packages/coin-ton/src/chain-wallet/wallet.ts create mode 100644 packages/coin-ton/src/index.ts create mode 100644 packages/coin-ton/src/ton-connect/index.ts create mode 100644 packages/coin-ton/src/ton-connect/types.ts create mode 100644 packages/coin-ton/src/vite-env.d.ts create mode 100644 packages/coin-ton/tsconfig.json create mode 100644 packages/coin-ton/vite.config.ts create mode 100644 packages/coin-tron/.gitignore create mode 100644 packages/coin-tron/.prettierignore create mode 100644 packages/coin-tron/package.json create mode 100644 packages/coin-tron/src/chain-wallet/chain.ts create mode 100644 packages/coin-tron/src/chain-wallet/index.ts create mode 100644 packages/coin-tron/src/chain-wallet/wallet.ts create mode 100644 packages/coin-tron/src/index.ts create mode 100644 packages/coin-tron/src/vite-env.d.ts create mode 100644 packages/coin-tron/tsconfig.json create mode 100644 packages/coin-tron/vite.config.ts diff --git a/package.json b/package.json index 7a1e9a14..bc4869ad 100644 --- a/package.json +++ b/package.json @@ -6,6 +6,11 @@ "build:sdk": "turbo run @delandlabs/hibit-id-wallet-sdk#build", "test:coin-kaspa": "turbo run @delandlabs/coin-kaspa#test", "build:coin-kaspa": "turbo run @delandlabs/coin-kaspa#build", + "build:coin-ethereum": "turbo run @delandlabs/coin-ethereum#build", + "build:coin-ton": "turbo run @delandlabs/coin-ton#build", + "build:coin-dfinity": "turbo run @delandlabs/coin-dfinity#build", + "build:coin-solana": "turbo run @delandlabs/coin-solana#build", + "build:coin-tron": "turbo run @delandlabs/coin-tron#build", "prepare": "husky install" }, "workspaces": [ diff --git a/packages/coin-base/.gitignore b/packages/coin-base/.gitignore new file mode 100644 index 00000000..a547bf36 --- /dev/null +++ b/packages/coin-base/.gitignore @@ -0,0 +1,24 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +dist +dist-ssr +*.local + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +.DS_Store +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? diff --git a/packages/coin-base/.prettierignore b/packages/coin-base/.prettierignore new file mode 100644 index 00000000..bfe3b8d3 --- /dev/null +++ b/packages/coin-base/.prettierignore @@ -0,0 +1 @@ +tsconfig.json \ No newline at end of file diff --git a/packages/coin-base/package.json b/packages/coin-base/package.json new file mode 100644 index 00000000..ce5d984c --- /dev/null +++ b/packages/coin-base/package.json @@ -0,0 +1,47 @@ +{ + "name": "@delandlabs/coin-base", + "private": false, + "version": "0.0.0", + "type": "module", + "files": [ + "dist" + ], + "main": "./dist/coin-base.umd.cjs", + "module": "./dist/coin-base.js", + "types": "dist/index.d.ts", + "exports": { + ".": { + "import": { + "types": "./dist/index.d.ts", + "default": "./dist/coin-base.js" + }, + "require": { + "types": "./dist/index.d.ts", + "default": "./dist/coin-base.umd.cjs" + } + } + }, + "scripts": { + "dev": "vite", + "test": "vitest", + "build": "vite build", + "lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0", + "format": "prettier --write ." + }, + "dependencies": { + "class-transformer": "^0.5.1", + "reflect-metadata": "^0.2.2" + }, + "devDependencies": { + "@eslint/js": "^9.16.0", + "@rollup/plugin-typescript": "^12.1.1", + "@typescript-eslint/eslint-plugin": "^8.16.0", + "@typescript-eslint/parser": "^8.16.0", + "eslint": "^9.16.0", + "globals": "^15.12.0", + "typescript": "~5.6.2", + "typescript-eslint": "^8.16.0", + "vite": "^6.0.1", + "vitest": "^2.1.6" + } +} diff --git a/packages/coin-base/src/enums.ts b/packages/coin-base/src/enums.ts new file mode 100644 index 00000000..644c1550 --- /dev/null +++ b/packages/coin-base/src/enums.ts @@ -0,0 +1,20 @@ +export enum WalletSignatureSchema { + BtcEcdsa = '0x3e8', + EvmEcdsa = '0x3e9', + TronEcdsa = '0x3ea', + TonEddsaOpenMask = '0x7d0', + SolanaEddsa = '0x7da', + IcpEddsa = '0x7e4', + KaspaSchnorr = '0xbc2', +} + +// TODO: Add support for other ecosystems +export enum Ecosystem { + EVM = 'EVM', + Bitcoin = 'Bitcoin', + Solana = 'Solana', + Tron = 'Tron', + Ton = 'Ton', + IC = 'Internet Computer', + Kaspa = 'Kaspa', +} diff --git a/packages/coin-base/src/index.ts b/packages/coin-base/src/index.ts new file mode 100644 index 00000000..f8a62046 --- /dev/null +++ b/packages/coin-base/src/index.ts @@ -0,0 +1,22 @@ +import 'reflect-metadata'; +import BigNumber from "bignumber.js"; +import { AssetInfo, ChainInfo, WalletAccount } from "./types"; + +export * from "./types" +export * from "./enums" + +export abstract class BaseChainWallet { + public readonly chainInfo: ChainInfo + protected readonly phrase: string + + constructor(chainInfo: ChainInfo, phrase: string) { + this.chainInfo = chainInfo + this.phrase = phrase + } + + public abstract getAccount: () => Promise + public abstract signMessage: (message: string) => Promise + public abstract balanceOf: (address: string, assetInfo: AssetInfo) => Promise + public abstract transfer: (toAddress: string, amount: BigNumber, assetInfo: AssetInfo) => Promise + public abstract getEstimatedFee: (toAddress: string, amount: BigNumber, assetInfo: AssetInfo) => Promise +} diff --git a/packages/coin-base/src/types.ts b/packages/coin-base/src/types.ts new file mode 100644 index 00000000..b9924fda --- /dev/null +++ b/packages/coin-base/src/types.ts @@ -0,0 +1,251 @@ +import BigNumber from "bignumber.js"; +import { Transform, Type } from 'class-transformer'; +import { WalletSignatureSchema, Ecosystem } from "./enums"; + +export class Chain { + value: BigNumber; + + constructor(value: BigNumber) { + this.value = value; + } + + static Bitcoin = new Chain(new BigNumber(0)); + static Ethereum = new Chain(new BigNumber(60)); + static Solana = new Chain(new BigNumber(501)); + static Dfinity = new Chain(new BigNumber(223)); + static Ton = new Chain(new BigNumber(607)); + static Tron = new Chain(new BigNumber(195)); + static Kaspa = new Chain(new BigNumber(111111)); + + static fromString(value: string): Chain | null { + if (!value) { + return null; + } + return new Chain(new BigNumber(value)); + } + + toString(): string { + return this.value.toString(); + } + + equals(other: Chain): boolean { + if (!other) { + return false; + } + return this.value.isEqualTo(other.value); + } +} + +export class ChainNetwork { + value: BigNumber; + + constructor(value: BigNumber) { + this.value = value; + } + + static MainNet = new ChainNetwork(new BigNumber(1)); + static TestNet = new ChainNetwork(new BigNumber(0)); + + static BtcMainNet = new ChainNetwork(new BigNumber(1)); + static BtcTestNet = new ChainNetwork(new BigNumber(2)); + + static EvmMainNet = new ChainNetwork(new BigNumber(0x1)); + static EvmSepoliaNet = new ChainNetwork(new BigNumber(0xaa36a7)); + static EvmBscNet = new ChainNetwork(new BigNumber(0x38)); + static EvmBscTestNet = new ChainNetwork(new BigNumber(97)); + static EvmBaseNet = new ChainNetwork(new BigNumber(8453)); + static EvmBaseSepoliaNet = new ChainNetwork(new BigNumber(84532)); + static EvmAvalancheNet = new ChainNetwork(new BigNumber(43114)); + static EvmAvalancheFujiNet = new ChainNetwork(new BigNumber(43113)); + static EvmScrollNet = new ChainNetwork(new BigNumber(534352)); + static EvmScrollSepoliaNet = new ChainNetwork(new BigNumber(534351)); + static EvmBitlayerNet = new ChainNetwork(new BigNumber(200901)); + static EvmBitlayerTestNet = new ChainNetwork(new BigNumber(200810)); + static EvmSwanNet = new ChainNetwork(new BigNumber(254)); + static EvmSwanTestNet = new ChainNetwork(new BigNumber(20241133)); + + static SolanaMainNet = new ChainNetwork(new BigNumber(0x3)); + static SolanaTestNet = new ChainNetwork(new BigNumber(0x2)); + + static TonMainNet = new ChainNetwork(new BigNumber(1)); + static TonTestNet = new ChainNetwork(new BigNumber(2)); + + static TronMainNet = new ChainNetwork(new BigNumber(0x2b6653dc)); + static TronShastaTestNet = new ChainNetwork(new BigNumber(0x94a9059e)); + static TronNileTestNet = new ChainNetwork(new BigNumber(0xcd8690dc)); + + static DfinityMainNet = new ChainNetwork(new BigNumber(1)); + + static KaspaMainNet = new ChainNetwork(new BigNumber(0)); + static KaspaTestNet = new ChainNetwork(new BigNumber(1)); + + static fromString(value: string): ChainNetwork | null { + if (!value) { + return null; + } + return new ChainNetwork(new BigNumber(value)); + } + + toString(): string { + return this.value.toString(); + } + + equals(other: ChainNetwork): boolean { + if (!other) { + return false; + } + return this.value.isEqualTo(other.value); + } +} + +export class ChainId { + type: Chain; + network: ChainNetwork; + + constructor(type: Chain, network: ChainNetwork) { + this.type = type; + this.network = network; + } + + static fromString(value: string): ChainId | null { + if (!value) { + return null; + } + const [type, network] = value.split('_'); + return new ChainId( + Chain.fromString(type)!, + ChainNetwork.fromString(network)! + ); + } + + toString(): string { + return `${this.type.toString()}_${this.network.toString()}`; + } + + equals(other: ChainId): boolean { + if (!other) { + return false; + } + return this.type.equals(other.type) && this.network.equals(other.network); + } +} + +export class ChainAssetType { + value: BigNumber; + + constructor(value: BigNumber) { + this.value = value; + } + + static Native = new ChainAssetType(new BigNumber(0)); + static NativeGas = new ChainAssetType(new BigNumber(1)); + static ERC20 = new ChainAssetType(new BigNumber(3)); + static ERC721 = new ChainAssetType(new BigNumber(4)); + static ICP = new ChainAssetType(new BigNumber(5)); + static ICRC3 = new ChainAssetType(new BigNumber(6)); + static BRC20 = new ChainAssetType(new BigNumber(7)); + static SPL = new ChainAssetType(new BigNumber(8)); + static TRC20 = new ChainAssetType(new BigNumber(9)); + static Jetton = new ChainAssetType(new BigNumber(10)); + static KRC20 = new ChainAssetType(new BigNumber(11)); + + static fromString(value: string): ChainAssetType | null { + if (!value) { + return null; + } + return new ChainAssetType(new BigNumber(value)); + } + + toString(): string { + return this.value.toString(); + } + + equals(other: ChainAssetType): boolean { + if (!other) { + return false; + } + return this.value.isEqualTo(other.value); + } +} + +export class DecimalPlaces { + value: number; + + constructor(value: number) { + this.value = value; + } + + static fromNumber(value: number): DecimalPlaces { + return new DecimalPlaces(value); + } + + toString(): string { + return this.value.toString(); + } + + equals(other: DecimalPlaces): boolean { + if (!other) { + return false; + } + return this.value === other.value; + } +} + +export class ChainInfo { + /** + * Chain id + * @type {ChainId} https://github.com/satoshilabs/slips/blob/master/slip-0044.md. + */ + @Type(() => ChainId) + @Transform( + ({ value }) => ChainId.fromString(`${value.type.value}_${value.network.value}`), + { + toClassOnly: true + } + ) + chainId!: ChainId; + name!: string; + fullName!: string; + icon!: string; + nativeAssetSymbol!: string; + nativeAssetDecimals!: number; + supportedSignaturesSchemas!: WalletSignatureSchema[]; + explorer!: string; + rpcUrls!: string[]; + isMainnet!: boolean + isNativeGas!: boolean; + ecosystem!: Ecosystem; + caseSensitiveAddress?: boolean; + getServerFormatAddress?: (address: string) => string | null + getTxLink?: (txId: string) => string + getAddressLink?: (address: string) => string +} + +export class AssetInfo { + @Type(() => Chain) + @Transform(({ value }) => Chain.fromString(value) ?? undefined, { + toClassOnly: true + }) + chain!: Chain; + @Type(() => ChainNetwork) + @Transform(({ value }) => ChainNetwork.fromString(value) ?? undefined, { + toClassOnly: true + }) + chainNetwork!: ChainNetwork; + @Type(() => ChainAssetType) + @Transform(({ value }) => ChainAssetType.fromString(value) ?? undefined, { + toClassOnly: true + }) + chainAssetType!: ChainAssetType; + contractAddress!: string; + @Type(() => DecimalPlaces) + @Transform(({ value }) => DecimalPlaces.fromNumber(value) ?? undefined, { + toClassOnly: true + }) + decimalPlaces!: DecimalPlaces; +} + +export interface WalletAccount { + address: string; + publicKey?: string; +} diff --git a/packages/coin-base/src/vite-env.d.ts b/packages/coin-base/src/vite-env.d.ts new file mode 100644 index 00000000..11f02fe2 --- /dev/null +++ b/packages/coin-base/src/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/packages/coin-base/tsconfig.json b/packages/coin-base/tsconfig.json new file mode 100644 index 00000000..f48fcfc8 --- /dev/null +++ b/packages/coin-base/tsconfig.json @@ -0,0 +1,12 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "baseUrl": ".", + "paths": { + "src/*": ["src/*"] + }, + "experimentalDecorators": true, + }, + "include": ["src"], + "exclude": ["**/node_modules"] +} diff --git a/packages/coin-base/vite.config.ts b/packages/coin-base/vite.config.ts new file mode 100644 index 00000000..f2a013dd --- /dev/null +++ b/packages/coin-base/vite.config.ts @@ -0,0 +1,38 @@ +import { defineConfig } from 'vite'; +import { resolve } from 'path'; +import typescript from '@rollup/plugin-typescript'; + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [], + resolve: { + alias: { + src: resolve(__dirname, 'src') + } + }, + build: { + lib: { + // Could also be a dictionary or array of multiple entry points + entry: resolve(__dirname, 'src/index.ts'), + name: 'CoinBase', + // the proper extensions will be added + fileName: 'coin-base' + }, + commonjsOptions: { + transformMixedEsModules: true, + include: [/node_modules/] + }, + rollupOptions: { + plugins: [ + typescript({ + target: 'es2020', + rootDir: resolve(__dirname, 'src'), + declaration: true, + declarationDir: resolve(__dirname, 'dist'), + exclude: [resolve(__dirname, 'node_modules/**'), resolve(__dirname, 'test/**')], + allowSyntheticDefaultImports: true + }) + ] + } + } +}); diff --git a/packages/coin-dfinity/.gitignore b/packages/coin-dfinity/.gitignore new file mode 100644 index 00000000..a547bf36 --- /dev/null +++ b/packages/coin-dfinity/.gitignore @@ -0,0 +1,24 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +dist +dist-ssr +*.local + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +.DS_Store +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? diff --git a/packages/coin-dfinity/.prettierignore b/packages/coin-dfinity/.prettierignore new file mode 100644 index 00000000..bfe3b8d3 --- /dev/null +++ b/packages/coin-dfinity/.prettierignore @@ -0,0 +1 @@ +tsconfig.json \ No newline at end of file diff --git a/packages/coin-dfinity/package.json b/packages/coin-dfinity/package.json new file mode 100644 index 00000000..21282cc6 --- /dev/null +++ b/packages/coin-dfinity/package.json @@ -0,0 +1,56 @@ +{ + "name": "@delandlabs/coin-dfinity", + "private": false, + "version": "0.0.0", + "type": "module", + "files": [ + "dist" + ], + "main": "./dist/coin-dfinity.umd.cjs", + "module": "./dist/coin-dfinity.js", + "types": "dist/index.d.ts", + "exports": { + ".": { + "import": { + "types": "./dist/index.d.ts", + "default": "./dist/coin-dfinity.js" + }, + "require": { + "types": "./dist/index.d.ts", + "default": "./dist/coin-dfinity.umd.cjs" + } + } + }, + "scripts": { + "dev": "vite", + "test": "vitest", + "build": "vite build", + "lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0", + "format": "prettier --write ." + }, + "dependencies": { + "@delandlabs/coin-base": "*", + "@dfinity/agent": "^2.1.1", + "@dfinity/candid": "^2.1.1", + "@dfinity/identity-secp256k1": "^2.1.1", + "@dfinity/ledger-icp": "^2.5.0", + "@dfinity/ledger-icrc": "^2.5.0", + "@dfinity/principal": "^2.1.1", + "@dfinity/utils": "^2.5.0", + "@noble/secp256k1": "^1.7.0", + "ic0": "^0.2.8", + "cborg": "^4.2.4" + }, + "devDependencies": { + "@eslint/js": "^9.16.0", + "@rollup/plugin-typescript": "^12.1.1", + "@typescript-eslint/eslint-plugin": "^8.16.0", + "@typescript-eslint/parser": "^8.16.0", + "eslint": "^9.16.0", + "globals": "^15.12.0", + "typescript": "~5.6.2", + "typescript-eslint": "^8.16.0", + "vite": "^6.0.1", + "vitest": "^2.1.6" + } +} diff --git a/packages/coin-dfinity/src/chain-wallet/chain.ts b/packages/coin-dfinity/src/chain-wallet/chain.ts new file mode 100644 index 00000000..d826ec85 --- /dev/null +++ b/packages/coin-dfinity/src/chain-wallet/chain.ts @@ -0,0 +1,29 @@ +import { ChainInfo, ChainId, Chain, ChainNetwork, Ecosystem, WalletSignatureSchema } from "@delandlabs/coin-base"; + +export const Dfinity: ChainInfo = { + chainId: new ChainId(Chain.Dfinity, ChainNetwork.DfinityMainNet), + name: 'InternetComputer', + fullName: 'InternetComputer Mainnet', + icon: '/chain-icons/IC.svg', + nativeAssetSymbol: 'ICP', + nativeAssetDecimals: 8, + isMainnet: true, + isNativeGas: false, + ecosystem: Ecosystem.IC, + supportedSignaturesSchemas: [WalletSignatureSchema.IcpEddsa], + explorer: 'https://dashboard.internetcomputer.org', + rpcUrls: ['https://ic0.app'], + getTxLink: (txId: string) => { + if (typeof txId !== 'string') { + return '' + } + const hash = txId.startsWith('0x') ? txId.slice(2) : txId; + return `https://dashboard.internetcomputer.org/transaction/${hash}` + }, + getAddressLink: (address: string) => { + if (typeof address !== 'string') { + return '' + } + return `https://dashboard.internetcomputer.org/account/${address}` + }, +}; diff --git a/packages/coin-dfinity/src/chain-wallet/index.ts b/packages/coin-dfinity/src/chain-wallet/index.ts new file mode 100644 index 00000000..9a1efe87 --- /dev/null +++ b/packages/coin-dfinity/src/chain-wallet/index.ts @@ -0,0 +1,4 @@ +export * from './chain' +export * from './wallet' +export * from './types' +export * from './utils' diff --git a/packages/coin-dfinity/src/chain-wallet/types.ts b/packages/coin-dfinity/src/chain-wallet/types.ts new file mode 100644 index 00000000..ac301922 --- /dev/null +++ b/packages/coin-dfinity/src/chain-wallet/types.ts @@ -0,0 +1,144 @@ +export enum IcrcMethods { + // ICRC-25 + ICRC25_REQUEST_PERMISSIONS = 'icrc25_request_permissions', + ICRC25_PERMISSIONS = 'icrc25_permissions', + ICRC25_SUPPORTED_STANDARDS = 'icrc25_supported_standards', + // ICRC-27 + ICRC27_ACCOUNTS = 'icrc27_accounts', + // ICRC-29 + ICRC29_STATUS = 'icrc29_status', + // ICRC-32 + ICRC32_SIGN_CHALLENGE = 'icrc32_sign_challenge', + // ICRC-49 + ICRC49_CALL_CANISTER = 'icrc49_call_canister' +} + +export enum IcrcPermissionState { + GRANTED = 'granted', + DENIED = 'denied', + ASK_ON_USE = 'ask_on_use' +} + +export enum IcrcErrorCode { + GenericError = 1000, + NotSupported = 2000, + PermissionNotGranted = 3000, + ActionAborted = 3001, + NetworkError = 4000, + TransportChannelClosed = 4001, +} + +export const IcrcErrorCodeMessages: Record = { + [IcrcErrorCode.GenericError]: 'Generic error', + [IcrcErrorCode.NotSupported]: 'Not supported', + [IcrcErrorCode.PermissionNotGranted]: 'Permission not granted', + [IcrcErrorCode.ActionAborted]: 'Action aborted', + [IcrcErrorCode.NetworkError]: 'Network error', + [IcrcErrorCode.TransportChannelClosed]: 'Transport channel closed', +} + +export type JsonRpcRequest = { + id: number; + jsonrpc: '2.0'; + method: IcrcMethods; + params?: unknown[]; +}; + +export type JsonRpcResponseSuccess = { + id: number; + jsonrpc: '2.0'; + result: TResult +}; + +export type JsonRpcResponseError = { + id: number; + jsonrpc: '2.0'; + error: { + code: number; + message: string; + description?: string; + }; +}; + +export type Icrc25RequestPermissionsRequest = JsonRpcRequest & { + method: IcrcMethods.ICRC25_REQUEST_PERMISSIONS; + params: { + scopes: Array<{ method: IcrcMethods }>; + }; +}; + +export type Icrc25RequestPermissionsResult = { + scopes: Array<{ + scope: { + method: IcrcMethods; + }; + state: IcrcPermissionState + }>; +}; + +export type Icrc25PermissionsRequest = JsonRpcRequest & { + method: IcrcMethods.ICRC25_PERMISSIONS; + params: undefined +}; + +export type Icrc25PermissionsResult = Icrc25RequestPermissionsResult + +export type Icrc25SupportedStandardsRequest = JsonRpcRequest & { + method: IcrcMethods.ICRC25_SUPPORTED_STANDARDS; + params: undefined +}; + +export type Icrc25SupportedStandardsResult = { + supportedStandards: Array<{ + name: string, + url: string + }>; +}; + +export type Icrc27AccountsRequest = JsonRpcRequest & { + method: IcrcMethods.ICRC27_ACCOUNTS; + params: undefined +}; + +export type Icrc27AccountsResult = { + accounts: Array<{ + owner: string + subaccount?: string + }>; +}; + +export type Icrc29StatusRequest = JsonRpcRequest & { + method: IcrcMethods.ICRC29_STATUS; + params: undefined +}; + +export type Icrc29StatusResult = "ready" + +export type Icrc32SignChallengeRequest = JsonRpcRequest & { + method: IcrcMethods.ICRC32_SIGN_CHALLENGE; + params: { + principal: string + challenge: string // base64 encoded + } +}; + +export type Icrc32SignChallengeResult = { + publicKey: string + signature: string +}; + +export type Icrc49CallCanisterRequest = JsonRpcRequest & { + method: IcrcMethods.ICRC49_CALL_CANISTER + params: { + canisterId: string + sender: string + method: string + arg: string // base64 encoded + nonce?: string // base64 encoded + } +} + +export type Icrc49CallCanisterResult = { + contentMap: string // base64 encoded + certificate: string // base64 encoded +} diff --git a/packages/coin-dfinity/src/chain-wallet/utils.ts b/packages/coin-dfinity/src/chain-wallet/utils.ts new file mode 100644 index 00000000..1126a844 --- /dev/null +++ b/packages/coin-dfinity/src/chain-wallet/utils.ts @@ -0,0 +1,105 @@ +import { Principal } from "@dfinity/principal" +import { IcrcMethods, IcrcPermissionState, JsonRpcRequest, JsonRpcResponseError, JsonRpcResponseSuccess } from "./types" +import { AccountIdentifier } from "@dfinity/ledger-icp" + +const ICRC_SESSION_KEY = 'icrc29_session' + +type Icrc29Session = { + establishedOrigin: string + permissions: Record +} + +// TODO: grow as implement more standards +export const SUPPORTED_STANDARDS = [ + { + name: 'ICRC-25', + url: 'https://github.com/dfinity/ICRC/blob/main/ICRCs/ICRC-25/ICRC-25.md', + }, + { + name: 'ICRC-27', + url: 'https://github.com/dfinity/ICRC/blob/main/ICRCs/ICRC-27/ICRC-27.md', + }, + { + name: 'ICRC-29', + url: 'https://github.com/dfinity/ICRC/blob/main/ICRCs/ICRC-29/ICRC-29.md', + }, + { + name: 'ICRC-32', + url: 'https://github.com/dfinity/ICRC/blob/main/ICRCs/ICRC-32/ICRC-32.md', + }, + { + name: 'ICRC-49', + url: 'https://github.com/dfinity/ICRC/blob/main/ICRCs/ICRC-49/ICRC-49.md', + }, +] + +export const NEED_PERMISSION_METHODS = [ + IcrcMethods.ICRC27_ACCOUNTS, + IcrcMethods.ICRC32_SIGN_CHALLENGE, + IcrcMethods.ICRC49_CALL_CANISTER, +] + +export const getIcrc29Session = (): Icrc29Session | null => { + const session = sessionStorage.getItem(ICRC_SESSION_KEY) + if (!session) return null + return JSON.parse(session) as Icrc29Session +} + +export const setIcrc29Session = (origin: string, permissions: Icrc29Session['permissions']) => { + sessionStorage.setItem(ICRC_SESSION_KEY, JSON.stringify({ + establishedOrigin: origin, + permissions, + } as Icrc29Session)) +} + +export const parseJsonRpcRequest = (data: any): JsonRpcRequest => { + if (typeof data !== 'object') throw new Error('Invalid JSON-RPC request: malformed data') + if (data.jsonrpc !== '2.0') throw new Error('Invalid JSON-RPC request: invalid version') + if (!Object.values(IcrcMethods).includes(data.method)) throw new Error('Invalid JSON-RPC request: invalid method') + return data as JsonRpcRequest +} + +export const buildJsonRpcResponse = (id: number, result: TResult): JsonRpcResponseSuccess => { + return { + id, + jsonrpc: '2.0', + result, + } +} + +export const buildJsonRpcError = (id: number, code: number, message: string, desc?: string): JsonRpcResponseError => { + return { + id, + jsonrpc: '2.0', + error: { + code, + message, + description: desc, + }, + } +} + +export const isAddressPrincipal = (address: string): boolean => { + try { + Principal.fromText(address) + return true + } catch (e) { + return false + } +} + +export const isAddressAccountIdentifier = (address: string): boolean => { + return /^[a-fA-F0-9]{64}$/i.test(address) +} + +export const getAccountIdentifierByAddress = (address: string): AccountIdentifier | null => { + if (isAddressPrincipal(address)) { + return AccountIdentifier.fromPrincipal({ + principal: Principal.fromText(address), + }) + } + if (isAddressAccountIdentifier(address)) { + return AccountIdentifier.fromHex(address) + } + return null +} diff --git a/packages/coin-dfinity/src/chain-wallet/wallet.test.ts b/packages/coin-dfinity/src/chain-wallet/wallet.test.ts new file mode 100644 index 00000000..c7b2c901 --- /dev/null +++ b/packages/coin-dfinity/src/chain-wallet/wallet.test.ts @@ -0,0 +1,50 @@ +import { expect, test, vitest } from 'vitest'; +import { Secp256k1KeyIdentity } from '@dfinity/identity-secp256k1'; +import { secp256k1 } from '@noble/curves/secp256k1'; +import { sha256 } from '@noble/hashes/sha256'; +// set timeout to 60 seconds +vitest.setConfig({ + testTimeout: 60000 +}); + +const privateKeyHex = '73f22e6591b8d004c784352e83fdb61126f70275a34c28430e0512a341084662'; +const publicKeyHex = '04190ca1014addc5e6e19f18ffa6af682f9e01b00a88afa713d493acc5075e0391c685568f9b1bfd2cea15e9fda1793eb75517a5c946d4be80acd21020052771cd'; +const identity = Secp256k1KeyIdentity.fromSecretKey(Buffer.from(privateKeyHex, 'hex')); +expect(Buffer.from(identity.getPublicKey().toRaw()).toString('hex')).toBe(publicKeyHex); +expect(identity.getPrincipal().toText()).toBe('2iudo-gq3ht-c4bvx-chdaa-ksfid-33wt7-2seu2-s35yw-coch4-3k44l-pqe'); + + +test('sign', async () => { + const message = 'nice'; + const messageBytes = Buffer.from(message, 'utf8'); + const hash = sha256(Buffer.from(messageBytes)); + const signature = await identity.sign(messageBytes); + expect(Buffer.from(signature).toString('hex')).toBe('3dfe32750ce59b403d60126ad3bcf8ff8766419c96c418d6e546edb5b9e24484434e2ee1f4b78b6a69417ece4646de4ad79ddfc5e1f1694ad2523761ca6aa2b6'); + + // verify signature with public key + const publicKey = identity.getPublicKey(); + expect(secp256k1.verify(Buffer.from(signature), Buffer.from(hash), Buffer.from(publicKey.rawKey))) + .toBe(true); +}); + + +test('sign wallet request', async () => { + // sign + const message = `subject: wallet registration\nchain: 0xdf\nsign_schema: 0x7e4\npub_key: 0x${publicKeyHex}`; + const messageBytes = Buffer.from(message, 'utf8'); + console.log('messageBytes', Buffer.from(messageBytes).toString('hex')); + const signature = await identity.sign(messageBytes); + expect(Buffer.from(signature).toString('hex')).toBe('67c2a4c5c17fb8ff54fdf7f6b6f4fe1f47f9274ad8fb2f924e2527e712bd765966b614426b7d10d597158403a58394bd32307cc501260424d9c473bfac5382f6'); + + // verify signature with public key + const publicKey = identity.getPublicKey(); + const hash = sha256(Buffer.from(messageBytes)); + expect(secp256k1.verify(Buffer.from(signature), Buffer.from(hash), Buffer.from(publicKey.rawKey))) + .toBe(true); +}); + + + + + + diff --git a/packages/coin-dfinity/src/chain-wallet/wallet.ts b/packages/coin-dfinity/src/chain-wallet/wallet.ts new file mode 100644 index 00000000..8dd93eca --- /dev/null +++ b/packages/coin-dfinity/src/chain-wallet/wallet.ts @@ -0,0 +1,231 @@ +import BigNumber from "bignumber.js"; +import { Buffer } from 'buffer/'; +import { WalletAccount } from "@delandlabs/hibit-id-wallet-sdk"; +import { Secp256k1KeyIdentity } from '@dfinity/identity-secp256k1'; +import { createAgent } from '@dfinity/utils' +import { HttpAgent, v3ResponseBody } from "@dfinity/agent"; +import { AccountIdentifier, LedgerCanister } from '@dfinity/ledger-icp' +import { IcrcLedgerCanister, IcrcMetadataResponseEntries } from "@dfinity/ledger-icrc"; +import { Principal } from "@dfinity/principal"; +import { Icrc25SupportedStandardsResult, Icrc49CallCanisterRequest, Icrc49CallCanisterResult, IcrcErrorCode, JsonRpcResponseError, JsonRpcResponseSuccess } from "./types"; +import { buildJsonRpcError, buildJsonRpcResponse } from "./utils"; +import * as cbor from 'cborg'; +import ic from 'ic0' +import { AssetInfo, BaseChainWallet, Chain, ChainAssetType, ChainInfo } from "@delandlabs/coin-base"; + +const ICP_LEDGER_CANISTER_ID = Principal.fromText('ryjl3-tyaaa-aaaaa-aaaba-cai'); + +export class DfinityChainWallet extends BaseChainWallet { + private identity: Secp256k1KeyIdentity | null = null + private agent: HttpAgent | null = null + private readyPromise: Promise + private feeCache: Record = {} + + constructor(chainInfo: ChainInfo, phrase: string) { + if (!chainInfo.chainId.type.equals(Chain.Dfinity)) { + throw new Error('Dfinity: invalid chain type'); + } + super(chainInfo, phrase) + this.readyPromise = new Promise((resolve) => { + this.initWallet(phrase).then(resolve) + }) + } + + public override getAccount: () => Promise = async () => { + await this.readyPromise + const address = this.identity!.getPrincipal().toString() + return { + address, + publicKey: Buffer.from(this.identity!.getPublicKey().toRaw()).toString('hex'), + } as WalletAccount + } + + public override signMessage: (message: string) => Promise = async (message) => { + if (!message) { + throw new Error('Dfinity: Missing sign data'); + } + await this.readyPromise + const signature = await this.identity!.sign(Buffer.from(message, "utf8")) + return Buffer.from(signature).toString('hex') + } + + public override balanceOf = async (address: string, assetInfo: AssetInfo) => { + if (!assetInfo.chain.equals(Chain.Dfinity)) { + throw new Error('Dfinity: invalid asset chain'); + } + + await this.readyPromise + // ICP + if (assetInfo.chainAssetType.equals(ChainAssetType.ICP)) { + const ledger = this.getIcpLedger(); + const balance = await ledger.accountBalance({ + accountIdentifier: AccountIdentifier.fromPrincipal({ + principal: Principal.fromText(address) + }) + }) + return new BigNumber(String(balance)).shiftedBy(-assetInfo.decimalPlaces.value) + } + // ICRC + if (assetInfo.chainAssetType.equals(ChainAssetType.ICRC3)) { + await this.assertIcrc3Support(assetInfo.contractAddress) + const ledger = this.getIcrcLedger(assetInfo.contractAddress) + const balance = await ledger.balance({ + owner: Principal.fromText(address) + }) + const decimals = assetInfo.decimalPlaces?.value ?? (await this.getIcrcDecimals(ledger)) + return new BigNumber(String(balance)).shiftedBy(-decimals) + } + + throw new Error(`Dfinity: unsupported chain asset type ${assetInfo.chainAssetType.toString()}`); + }; + + public override transfer = async (toAddress: string, amount: BigNumber, assetInfo: AssetInfo) => { + if (!assetInfo.chain.equals(Chain.Dfinity)) { + throw new Error('Dfinity: invalid asset chain'); + } + await this.readyPromise + + // ICP + if (assetInfo.chainAssetType.equals(ChainAssetType.ICP)) { + const ledger = this.getIcpLedger() + const blockHeight = await ledger.transfer({ + to: AccountIdentifier.fromPrincipal({ + principal: Principal.fromText(toAddress) + }), + amount: BigInt(amount.shiftedBy(assetInfo.decimalPlaces.value).toString()) + }) + console.debug(`Dfinity: ICP transfer blockHeight ${blockHeight}`) + return String(blockHeight) + } + // ICRC + if (assetInfo.chainAssetType.equals(ChainAssetType.ICRC3)) { + await this.assertIcrc3Support(assetInfo.contractAddress) + const ledger = this.getIcrcLedger(assetInfo.contractAddress) + const decimals = assetInfo.decimalPlaces?.value ?? (await this.getIcrcDecimals(ledger)) + const blockIndex = await ledger.transfer({ + to: { + owner: Principal.fromText(toAddress), + subaccount: [], + }, + amount: BigInt(amount.shiftedBy(decimals).toString()), + }) + console.debug(`Dfinity: ICRC transfer blockIndex ${blockIndex}`) + return String(blockIndex) + } + + throw new Error(`Dfinity: unsupported chain asset type ${assetInfo.chainAssetType.toString()}`); + } + + public override getEstimatedFee = async (toAddress: string, amount: BigNumber, assetInfo: AssetInfo): Promise => { + if (!assetInfo.chain.equals(Chain.Dfinity)) { + throw new Error('Dfinity: invalid asset chain'); + } + await this.readyPromise + + // ICP + if (assetInfo.chainAssetType.equals(ChainAssetType.ICP)) { + if (this.feeCache['native']) { + return this.feeCache['native'] + } + const ledger = this.getIcpLedger() + const fee = await ledger.transactionFee() + const result = new BigNumber(String(fee)).shiftedBy(-assetInfo.decimalPlaces.value) + this.feeCache['native'] = result + return result + } + + // ICRC + if (assetInfo.chainAssetType.equals(ChainAssetType.ICRC3)) { + if (this.feeCache[assetInfo.contractAddress]) { + return this.feeCache[assetInfo.contractAddress] + } + await this.assertIcrc3Support(assetInfo.contractAddress) + const ledger = this.getIcrcLedger(assetInfo.contractAddress) + const fee = await ledger.transactionFee({}) + const decimals = assetInfo.decimalPlaces?.value ?? (await this.getIcrcDecimals(ledger)) + const result = new BigNumber(String(fee)).shiftedBy(-decimals) + this.feeCache[assetInfo.contractAddress] = result + return result + } + + throw new Error(`Dfinity: unsupported chain asset type ${assetInfo.chainAssetType.toString()}`); + } + + public Icrc49CallCanister = async (request: Icrc49CallCanisterRequest): Promise | JsonRpcResponseError> => { + await this.readyPromise + try { + const params = request.params + const response = await this.agent!.call( + params.canisterId, + { + methodName: params.method, + arg: Buffer.from(params.arg, 'base64'), + callSync: true, + } + ) + if (response.response.status > 202) { + throw new Error(`ICRC49 call failed with http status ${response.response.status}`) + } + return buildJsonRpcResponse(request.id, { + contentMap: Buffer.from(cbor.encode(response.requestDetails)).toString('base64'), + certificate: Buffer.from((response.response.body as v3ResponseBody)?.certificate!).toString('base64'), + }) + } catch (e: any) { + return buildJsonRpcError(request.id, IcrcErrorCode.GenericError, e.message ?? JSON.stringify(e)) + } + } + + private initWallet = async (phrase: string) => { + this.identity = Secp256k1KeyIdentity.fromSeedPhrase(phrase) + // this.agent = await createAgent({ + // identity: this.identity, + // host: RUNTIME_ICRC_HOST || this.chainInfo.rpcUrls[0], + // fetchRootKey: RUNTIME_ICRC_DEV, + // }) + this.agent = await createAgent({ + identity: this.identity, + host: this.chainInfo.rpcUrls[0], + }) + } + + private getIcpLedger = () => { + return LedgerCanister.create({ + agent: this.agent!, + canisterId: ICP_LEDGER_CANISTER_ID, + }) + } + + private getIcrcLedger = (canisterId: string) => { + return IcrcLedgerCanister.create({ + agent: this.agent!, + canisterId: Principal.fromText(canisterId), + }) + } + + private getIcrcDecimals = async (ledger: IcrcLedgerCanister) => { + let decimals = 8 + const metaData = await ledger.metadata({}) + for (const entry of metaData) { + if (entry[0] === IcrcMetadataResponseEntries.DECIMALS) { + decimals = Number(String((entry[1] as any).Nat)) + break; + } + } + return decimals + } + + private assertIcrc3Support = async (canisterId: string) => { + try { + const ledger = ic(canisterId) + const response: Icrc25SupportedStandardsResult['supportedStandards'] + = await ledger.call('icrc1_supported_standards') + + console.debug('icrc1_supported_standards',canisterId, response) + if (!Array.isArray(response) || !response.find((standard) => standard?.name.toUpperCase() === 'ICRC-3')) { + throw new Error(`Dfinity: token(${canisterId}) does not support ICRC-3`) + } + } catch (e) { + throw new Error(`Dfinity: failed to check ICRC-3 support of token(${canisterId})`) + } + } +} diff --git a/packages/coin-dfinity/src/index.ts b/packages/coin-dfinity/src/index.ts new file mode 100644 index 00000000..02d3efed --- /dev/null +++ b/packages/coin-dfinity/src/index.ts @@ -0,0 +1 @@ +export * from './chain-wallet' diff --git a/packages/coin-dfinity/src/vite-env.d.ts b/packages/coin-dfinity/src/vite-env.d.ts new file mode 100644 index 00000000..11f02fe2 --- /dev/null +++ b/packages/coin-dfinity/src/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/packages/coin-dfinity/tsconfig.json b/packages/coin-dfinity/tsconfig.json new file mode 100644 index 00000000..f48fcfc8 --- /dev/null +++ b/packages/coin-dfinity/tsconfig.json @@ -0,0 +1,12 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "baseUrl": ".", + "paths": { + "src/*": ["src/*"] + }, + "experimentalDecorators": true, + }, + "include": ["src"], + "exclude": ["**/node_modules"] +} diff --git a/packages/coin-dfinity/vite.config.ts b/packages/coin-dfinity/vite.config.ts new file mode 100644 index 00000000..7fd15cbb --- /dev/null +++ b/packages/coin-dfinity/vite.config.ts @@ -0,0 +1,38 @@ +import { defineConfig } from 'vite'; +import { resolve } from 'path'; +import typescript from '@rollup/plugin-typescript'; + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [], + resolve: { + alias: { + src: resolve(__dirname, 'src') + } + }, + build: { + lib: { + // Could also be a dictionary or array of multiple entry points + entry: resolve(__dirname, 'src/index.ts'), + name: 'CoinDfinity', + // the proper extensions will be added + fileName: 'coin-dfinity' + }, + commonjsOptions: { + transformMixedEsModules: true, + include: [/node_modules/] + }, + rollupOptions: { + plugins: [ + typescript({ + target: 'es2020', + rootDir: resolve(__dirname, 'src'), + declaration: true, + declarationDir: resolve(__dirname, 'dist'), + exclude: [resolve(__dirname, 'node_modules/**'), resolve(__dirname, 'test/**')], + allowSyntheticDefaultImports: true + }) + ] + } + } +}); diff --git a/packages/coin-ethereum/.gitignore b/packages/coin-ethereum/.gitignore new file mode 100644 index 00000000..a547bf36 --- /dev/null +++ b/packages/coin-ethereum/.gitignore @@ -0,0 +1,24 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +dist +dist-ssr +*.local + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +.DS_Store +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? diff --git a/packages/coin-ethereum/.prettierignore b/packages/coin-ethereum/.prettierignore new file mode 100644 index 00000000..bfe3b8d3 --- /dev/null +++ b/packages/coin-ethereum/.prettierignore @@ -0,0 +1 @@ +tsconfig.json \ No newline at end of file diff --git a/packages/coin-ethereum/package.json b/packages/coin-ethereum/package.json new file mode 100644 index 00000000..88956f97 --- /dev/null +++ b/packages/coin-ethereum/package.json @@ -0,0 +1,47 @@ +{ + "name": "@delandlabs/coin-ethereum", + "private": false, + "version": "0.0.0", + "type": "module", + "files": [ + "dist" + ], + "main": "./dist/coin-ethereum.umd.cjs", + "module": "./dist/coin-ethereum.js", + "types": "dist/index.d.ts", + "exports": { + ".": { + "import": { + "types": "./dist/index.d.ts", + "default": "./dist/coin-ethereum.js" + }, + "require": { + "types": "./dist/index.d.ts", + "default": "./dist/coin-ethereum.umd.cjs" + } + } + }, + "scripts": { + "dev": "vite", + "test": "vitest", + "build": "vite build", + "lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0", + "format": "prettier --write ." + }, + "dependencies": { + "@delandlabs/coin-base": "*", + "ethers": "^6.13.1" + }, + "devDependencies": { + "@eslint/js": "^9.16.0", + "@rollup/plugin-typescript": "^12.1.1", + "@typescript-eslint/eslint-plugin": "^8.16.0", + "@typescript-eslint/parser": "^8.16.0", + "eslint": "^9.16.0", + "globals": "^15.12.0", + "typescript": "~5.6.2", + "typescript-eslint": "^8.16.0", + "vite": "^6.0.1", + "vitest": "^2.1.6" + } +} diff --git a/packages/coin-ethereum/src/chain-wallet/chain.ts b/packages/coin-ethereum/src/chain-wallet/chain.ts new file mode 100644 index 00000000..40e33dff --- /dev/null +++ b/packages/coin-ethereum/src/chain-wallet/chain.ts @@ -0,0 +1,204 @@ +import { ChainInfo, ChainId, Chain, ChainNetwork, Ecosystem, WalletSignatureSchema } from "@delandlabs/coin-base"; + +export const Ethereum: ChainInfo = { + chainId: new ChainId(Chain.Ethereum, ChainNetwork.EvmMainNet), + name: 'Ethereum', + fullName: 'Ethereum Mainnet', + icon: '/chain-icons/Ethereum.svg', + nativeAssetSymbol: 'ETH', + nativeAssetDecimals: 18, + isMainnet: true, + isNativeGas: true, + ecosystem: Ecosystem.EVM, + supportedSignaturesSchemas: [WalletSignatureSchema.EvmEcdsa], + explorer: 'https://etherscan.io', + rpcUrls: ['https://ethereum.blockpi.network/v1/rpc/public'] +}; +export const EthereumSepolia: ChainInfo = { + chainId: new ChainId(Chain.Ethereum, ChainNetwork.EvmSepoliaNet), + name: 'ETH Sepolia', + fullName: 'ETH Sepolia Testnet', + icon: '/chain-icons/Ethereum.svg', + nativeAssetSymbol: 'ETH', + nativeAssetDecimals: 18, + isMainnet: false, + isNativeGas: true, + ecosystem: Ecosystem.EVM, + supportedSignaturesSchemas: [WalletSignatureSchema.EvmEcdsa], + explorer: 'https://sepolia.etherscan.io', + rpcUrls: ['https://ethereum-sepolia.blockpi.network/v1/rpc/public '] +}; + +export const EthereumBsc: ChainInfo = { + chainId: new ChainId(Chain.Ethereum, ChainNetwork.EvmBscNet), + name: 'BSC', + fullName: 'BNB Smart Chain', + icon: '/chain-icons/BNB.svg', + nativeAssetSymbol: 'BNB', + nativeAssetDecimals: 18, + isMainnet: true, + isNativeGas: true, + ecosystem: Ecosystem.EVM, + supportedSignaturesSchemas: [WalletSignatureSchema.EvmEcdsa], + explorer: 'https://bscscan.com', + rpcUrls: ['https://bsc-dataseed.binance.org'] +}; +export const EthereumBscTestnet: ChainInfo = { + chainId: new ChainId(Chain.Ethereum, ChainNetwork.EvmBscTestNet), + name: 'BSC Testnet', + fullName: 'BNB Smart Chain Testnet', + icon: '/chain-icons/BNB.svg', + nativeAssetSymbol: 'tBNB', + nativeAssetDecimals: 18, + isMainnet: false, + isNativeGas: true, + ecosystem: Ecosystem.EVM, + supportedSignaturesSchemas: [WalletSignatureSchema.EvmEcdsa], + explorer: 'https://testnet.bscscan.com', + rpcUrls: ['https://bsc-testnet.publicnode.com'] +}; + +export const EthereumScroll: ChainInfo = { + chainId: new ChainId(Chain.Ethereum, ChainNetwork.EvmScrollNet), + name: 'Scroll', + fullName: 'Scroll Mainnet', + icon: '/chain-icons/Scroll.svg', + nativeAssetSymbol: 'ETH', + nativeAssetDecimals: 18, + isMainnet: true, + isNativeGas: true, + ecosystem: Ecosystem.EVM, + supportedSignaturesSchemas: [WalletSignatureSchema.EvmEcdsa], + explorer: 'https://scroll.l2scan.co', + rpcUrls: ['https://rpc.scroll.io'] +}; +export const EthereumScrollSepolia: ChainInfo = { + chainId: new ChainId(Chain.Ethereum, ChainNetwork.EvmScrollSepoliaNet), + name: 'Scroll Sepolia', + fullName: 'Scroll Sepolia Testnet', + icon: '/chain-icons/Scroll.svg', + nativeAssetSymbol: 'ETH', + nativeAssetDecimals: 18, + isMainnet: false, + isNativeGas: true, + ecosystem: Ecosystem.EVM, + supportedSignaturesSchemas: [WalletSignatureSchema.EvmEcdsa], + explorer: 'https://scroll-sepolia.l2scan.co', + rpcUrls: ['https://sepolia-rpc.scroll.io'] +}; + +export const EthereumBase: ChainInfo = { + chainId: new ChainId(Chain.Ethereum, ChainNetwork.EvmBscNet), + name: 'Base', + fullName: 'Base Mainnet', + icon: '/chain-icons/Base.svg', + nativeAssetSymbol: 'ETH', + nativeAssetDecimals: 18, + isMainnet: true, + isNativeGas: true, + ecosystem: Ecosystem.EVM, + supportedSignaturesSchemas: [WalletSignatureSchema.EvmEcdsa], + explorer: 'https://basescan.org', + rpcUrls: ['https://mainnet.base.org'] +}; +export const EthereumBaseSepolia: ChainInfo = { + chainId: new ChainId(Chain.Ethereum, ChainNetwork.EvmBaseSepoliaNet), + name: 'Base Sepolia', + fullName: 'Base Sepolia Testnet', + icon: '/chain-icons/Base.svg', + nativeAssetSymbol: 'ETH', + nativeAssetDecimals: 18, + isMainnet: false, + isNativeGas: true, + ecosystem: Ecosystem.EVM, + supportedSignaturesSchemas: [WalletSignatureSchema.EvmEcdsa], + explorer: 'https://sepolia.basescan.org', + rpcUrls: ['https://sepolia.base.org'] +}; + +export const EthereumAvalanche: ChainInfo = { + chainId: new ChainId(Chain.Ethereum, ChainNetwork.EvmAvalancheNet), + name: 'Avalanche', + fullName: 'Avalanche C-Chain', + icon: '/chain-icons/Avalanche.svg', + nativeAssetSymbol: 'AVAX', + nativeAssetDecimals: 18, + isMainnet: true, + isNativeGas: true, + ecosystem: Ecosystem.EVM, + supportedSignaturesSchemas: [WalletSignatureSchema.EvmEcdsa], + explorer: 'https://snowtrace.io', + rpcUrls: ['https://api.avax.network/ext/bc/C/rpc'] +}; +export const EthereumAvalancheFuji: ChainInfo = { + chainId: new ChainId(Chain.Ethereum, ChainNetwork.EvmAvalancheFujiNet), + name: 'Avalanche Fuji', + fullName: 'Avalanche Testnet C-Chain', + icon: '/chain-icons/Avalanche.svg', + nativeAssetSymbol: 'AVAX', + nativeAssetDecimals: 18, + isMainnet: false, + isNativeGas: true, + ecosystem: Ecosystem.EVM, + supportedSignaturesSchemas: [WalletSignatureSchema.EvmEcdsa], + explorer: 'https://subnets-test.avax.network/c-chain', + rpcUrls: ['https://api.avax-test.network/ext/bc/C/rpc'] +}; + +export const EthereumBitlayer: ChainInfo = { + chainId: new ChainId(Chain.Ethereum, ChainNetwork.EvmBitlayerNet), + name: 'Bitlayer', + fullName: 'Bitlayer Mainnet', + icon: '/chain-icons/Bitlayer.png', + nativeAssetSymbol: 'BTC', + nativeAssetDecimals: 18, + isMainnet: true, + isNativeGas: true, + ecosystem: Ecosystem.Bitcoin, + supportedSignaturesSchemas: [WalletSignatureSchema.EvmEcdsa], + explorer: 'https://btrscan.com', + rpcUrls: ['https://rpc.bitlayer.org'] +}; +export const EthereumBitlayerTestnet: ChainInfo = { + chainId: new ChainId(Chain.Ethereum, ChainNetwork.EvmBitlayerTestNet), + name: 'Bitlayer Testnet', + fullName: 'Bitlayer Testnet', + icon: '/chain-icons/Bitlayer.png', + nativeAssetSymbol: 'BTC', + nativeAssetDecimals: 18, + isMainnet: false, + isNativeGas: true, + ecosystem: Ecosystem.Bitcoin, + supportedSignaturesSchemas: [WalletSignatureSchema.EvmEcdsa], + explorer: 'https://testnet.btrscan.com', + rpcUrls: ['https://testnet-rpc.bitlayer.org'] +}; + +export const EthereumSwan: ChainInfo = { + chainId: new ChainId(Chain.Ethereum, ChainNetwork.EvmSwanNet), + name: 'Swan', + fullName: 'Swan Mainnet', + icon: '/chain-icons/Swan.svg', + nativeAssetSymbol: 'ETH', + nativeAssetDecimals: 18, + isMainnet: true, + isNativeGas: true, + ecosystem: Ecosystem.EVM, + supportedSignaturesSchemas: [WalletSignatureSchema.EvmEcdsa], + explorer: 'https://swanscan.io', + rpcUrls: ['https://mainnet-rpc.swanchain.org'] +}; +export const EthereumSwanTestnet: ChainInfo = { + chainId: new ChainId(Chain.Ethereum, ChainNetwork.EvmSwanTestNet), + name: 'Swan Testnet', + fullName: 'Swan Proxima Testnet', + icon: '/chain-icons/Swan.svg', + nativeAssetSymbol: 'ETH', + nativeAssetDecimals: 18, + isMainnet: false, + isNativeGas: true, + ecosystem: Ecosystem.EVM, + supportedSignaturesSchemas: [WalletSignatureSchema.EvmEcdsa], + explorer: 'https://proxima-explorer.swanchain.io', + rpcUrls: ['https://rpc-proxima.swanchain.io'] +}; diff --git a/packages/coin-ethereum/src/chain-wallet/index.ts b/packages/coin-ethereum/src/chain-wallet/index.ts new file mode 100644 index 00000000..10dab0e7 --- /dev/null +++ b/packages/coin-ethereum/src/chain-wallet/index.ts @@ -0,0 +1,2 @@ +export * from './chain' +export * from './wallet' diff --git a/packages/coin-ethereum/src/chain-wallet/utils.ts b/packages/coin-ethereum/src/chain-wallet/utils.ts new file mode 100644 index 00000000..a132f7b8 --- /dev/null +++ b/packages/coin-ethereum/src/chain-wallet/utils.ts @@ -0,0 +1,24 @@ +import { ChainId, ChainInfo } from '@delandlabs/coin-base'; +import * as EthereumChains from './chain' + +export const erc20Abi = [ + 'function name() view returns (string)', + 'function symbol() view returns (string)', + 'function decimals() view returns (uint8)', + 'function totalSupply() view returns (uint256)', + 'function balanceOf(address account) view returns (uint256)', + 'function transfer(address recipient, uint256 amount) returns (bool)', + + 'function allowance(address owner, address spender) view returns (uint256)', + 'function approve(address spender, uint256 amount) returns (bool)', + 'function transferFrom(address sender, address recipient, uint256 amount) returns (bool)', + + 'event Transfer(address indexed from, address indexed to, uint256 value)', + 'event Approval(address indexed owner, address indexed spender, uint256 value)' +]; + +export function getChain(chainId: ChainId | null): ChainInfo | null { + if (!chainId) return null; + const chains = Object.values(EthereumChains) + return chains.find(c => c.chainId.equals(chainId)) ?? null; +} diff --git a/packages/coin-ethereum/src/chain-wallet/wallet.ts b/packages/coin-ethereum/src/chain-wallet/wallet.ts new file mode 100644 index 00000000..735c8e31 --- /dev/null +++ b/packages/coin-ethereum/src/chain-wallet/wallet.ts @@ -0,0 +1,140 @@ +import BigNumber from "bignumber.js"; +import { isAddress, JsonRpcProvider, Contract, HDNodeWallet, parseEther, parseUnits, formatEther } from "ethers"; +import { erc20Abi, getChain } from "./utils"; +import { ChainInfo, Chain, AssetInfo, ChainAssetType, ChainId, BaseChainWallet, WalletAccount } from "@delandlabs/coin-base"; + +export class EthereumChainWallet extends BaseChainWallet { + private provider: JsonRpcProvider + private wallet: HDNodeWallet + + constructor(chainInfo: ChainInfo, phrase: string) { + if (!chainInfo.chainId.type.equals(Chain.Ethereum)) { + throw new Error('Ethereum: invalid chain type'); + } + super(chainInfo, phrase) + this.provider = new JsonRpcProvider( + this.chainInfo.rpcUrls[0], + this.chainInfo.chainId.network.value.toNumber() + ) + this.wallet = HDNodeWallet.fromPhrase(this.phrase) + this.wallet = this.wallet.connect(this.provider) + } + + public override getAccount: () => Promise = async () => { + return { + address: this.wallet.address + } + } + + public override signMessage: (message: string) => Promise = async (message) => { + const signature = await this.wallet.signMessage(message) + return signature + } + + public override balanceOf = async (address: string, assetInfo: AssetInfo) => { + if (!isAddress(address)) { + throw new Error('Ethereum: invalid wallet address'); + } + if (!assetInfo.chain.equals(Chain.Ethereum)) { + throw new Error('Ethereum: invalid asset chain'); + } + // native + if (assetInfo.chainAssetType.equals(ChainAssetType.Native)) { + const balance = await this.provider.getBalance(address); + return new BigNumber(balance.toString()).shiftedBy(-assetInfo.decimalPlaces.value) + } + // erc20 + if (assetInfo.chainAssetType.equals(ChainAssetType.ERC20)) { + const chainInfo = getChain(new ChainId(assetInfo.chain, assetInfo.chainNetwork)) + if (!chainInfo) { + throw new Error(`Ethereum: unsupported asset chain ${assetInfo.chain.toString()}_${assetInfo.chainNetwork.toString()}`) + } + const provider = new JsonRpcProvider(chainInfo.rpcUrls[0], chainInfo.chainId.network.value.toNumber()); + const contract = new Contract(assetInfo.contractAddress, erc20Abi, provider); + const getDecimals = contract.decimals(); + const getBalance = contract.balanceOf(address); + const [decimals, balance] = await Promise.all([getDecimals, getBalance]); + return new BigNumber(balance.toString()).shiftedBy(-Number(decimals)); + } + + throw new Error(`Ethereum: unsupported chain asset type ${assetInfo.chainAssetType.toString()}`); + }; + + public override transfer = async (toAddress: string, amount: BigNumber, assetInfo: AssetInfo) => { + if (!isAddress(toAddress)) { + throw new Error('Ethereum: invalid wallet address'); + } + if (!assetInfo.chain.equals(Chain.Ethereum)) { + throw new Error('Ethereum: invalid asset chain'); + } + try { + // native + if (assetInfo.chainAssetType.equals(ChainAssetType.Native)) { + const tx = await this.wallet.sendTransaction({ + to: toAddress, + value: parseEther(amount.toString()) + }); + return tx.hash; + } + // erc20 + if (assetInfo.chainAssetType.equals(ChainAssetType.ERC20)) { + const chainInfo = getChain(new ChainId(assetInfo.chain, assetInfo.chainNetwork)) + if (!chainInfo) { + throw new Error(`Ethereum: unsupported asset chain ${assetInfo.chain.toString()}_${assetInfo.chainNetwork.toString()}`) + } + const provider = new JsonRpcProvider(chainInfo.rpcUrls[0], chainInfo.chainId.network.value.toNumber()); + const token = new Contract(assetInfo.contractAddress, erc20Abi, this.wallet.connect(provider)); + const decimals = await token.decimals(); + const tx = await token + .getFunction('transfer')(toAddress, parseUnits(amount.toString(), decimals)); + return tx.hash; + } + } catch (e) { + console.error(e) + if ((e as any).code === 'INSUFFICIENT_FUNDS') { + throw new Error('Insufficient gas balance'); + } + throw e; + } + + throw new Error(`Ethereum: unsupported chain asset type ${assetInfo.chainAssetType.toString()}`); + } + + public override getEstimatedFee = async (toAddress: string, amount: BigNumber, assetInfo: AssetInfo): Promise => { + if (!isAddress(toAddress)) { + throw new Error('Ethereum: invalid wallet address'); + } + if (!assetInfo.chain.equals(Chain.Ethereum)) { + throw new Error('Ethereum: invalid asset chain'); + } + // native + if (assetInfo.chainAssetType.equals(ChainAssetType.Native)) { + const feeData = await this.wallet.provider!.getFeeData() + const price = new BigNumber(feeData.gasPrice!.toString()) + const req = { + to: toAddress, + value: parseEther(amount.toString()) + } + const estimatedGas = await this.wallet.estimateGas(req) + return new BigNumber(estimatedGas.toString()).times(price).shiftedBy(-assetInfo.decimalPlaces.value) + } + // erc20 + if (assetInfo.chainAssetType.equals(ChainAssetType.ERC20)) { + const chainInfo = getChain(new ChainId(assetInfo.chain, assetInfo.chainNetwork)) + if (!chainInfo) { + throw new Error(`Ethereum: unsupported asset chain ${assetInfo.chain.toString()}_${assetInfo.chainNetwork.toString()}`) + } + const provider = new JsonRpcProvider(chainInfo.rpcUrls[0], chainInfo.chainId.network.value.toNumber()); + const feeData = await provider!.getFeeData() + const price = new BigNumber(feeData.gasPrice!.toString()) + const token = new Contract(assetInfo.contractAddress, erc20Abi, this.wallet.connect(provider)); + const decimals = await token.decimals(); + const estimatedGas = await token + .getFunction('transfer') + .estimateGas(toAddress, parseUnits(amount.toString(), decimals)); + return new BigNumber(formatEther(new BigNumber(estimatedGas.toString()).times(price).toString())) + } + + throw new Error(`Ethereum: unsupported chain asset type ${assetInfo.chainAssetType.toString()}`); + } +} diff --git a/packages/coin-ethereum/src/index.ts b/packages/coin-ethereum/src/index.ts new file mode 100644 index 00000000..02d3efed --- /dev/null +++ b/packages/coin-ethereum/src/index.ts @@ -0,0 +1 @@ +export * from './chain-wallet' diff --git a/packages/coin-ethereum/src/vite-env.d.ts b/packages/coin-ethereum/src/vite-env.d.ts new file mode 100644 index 00000000..11f02fe2 --- /dev/null +++ b/packages/coin-ethereum/src/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/packages/coin-ethereum/tsconfig.json b/packages/coin-ethereum/tsconfig.json new file mode 100644 index 00000000..f48fcfc8 --- /dev/null +++ b/packages/coin-ethereum/tsconfig.json @@ -0,0 +1,12 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "baseUrl": ".", + "paths": { + "src/*": ["src/*"] + }, + "experimentalDecorators": true, + }, + "include": ["src"], + "exclude": ["**/node_modules"] +} diff --git a/packages/coin-ethereum/vite.config.ts b/packages/coin-ethereum/vite.config.ts new file mode 100644 index 00000000..7e17a9e2 --- /dev/null +++ b/packages/coin-ethereum/vite.config.ts @@ -0,0 +1,38 @@ +import { defineConfig } from 'vite'; +import { resolve } from 'path'; +import typescript from '@rollup/plugin-typescript'; + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [], + resolve: { + alias: { + src: resolve(__dirname, 'src') + } + }, + build: { + lib: { + // Could also be a dictionary or array of multiple entry points + entry: resolve(__dirname, 'src/index.ts'), + name: 'CoinEthereum', + // the proper extensions will be added + fileName: 'coin-ethereum' + }, + commonjsOptions: { + transformMixedEsModules: true, + include: [/node_modules/] + }, + rollupOptions: { + plugins: [ + typescript({ + target: 'es2020', + rootDir: resolve(__dirname, 'src'), + declaration: true, + declarationDir: resolve(__dirname, 'dist'), + exclude: [resolve(__dirname, 'node_modules/**'), resolve(__dirname, 'test/**')], + allowSyntheticDefaultImports: true + }) + ] + } + } +}); diff --git a/packages/coin-kaspa/package.json b/packages/coin-kaspa/package.json index dcc6b3a0..2a011db3 100644 --- a/packages/coin-kaspa/package.json +++ b/packages/coin-kaspa/package.json @@ -32,12 +32,14 @@ }, "dependencies": { "@delandlabs/crypto-lib": "*", + "@delandlabs/coin-base": "*", "buffer": "^6.0.3", "long": "^5.2.3", "nice-grpc-web": "^3.3.5", "protobufjs": "^7.4.0", "toml": "^3.0.0", - "websocket-heartbeat-js": "^1.1.3" + "websocket-heartbeat-js": "^1.1.3", + "ethers": "^6.13.1" }, "devDependencies": { "@eslint/js": "^9.16.0", diff --git a/packages/coin-kaspa/src/chain-wallet/chain.ts b/packages/coin-kaspa/src/chain-wallet/chain.ts new file mode 100644 index 00000000..8a4b1435 --- /dev/null +++ b/packages/coin-kaspa/src/chain-wallet/chain.ts @@ -0,0 +1,54 @@ +import { ChainInfo, ChainId, Chain, ChainNetwork, Ecosystem, WalletSignatureSchema } from "@delandlabs/coin-base"; + +export const Kaspa: ChainInfo = { + chainId: new ChainId(Chain.Kaspa, ChainNetwork.KaspaMainNet), + name: 'Kaspa', + fullName: 'Kaspa Mainnet', + icon: '/chain-icons/Kaspa.svg', + nativeAssetSymbol: 'KAS', + nativeAssetDecimals: 8, + isMainnet: true, + isNativeGas: true, + ecosystem: Ecosystem.Kaspa, + supportedSignaturesSchemas: [WalletSignatureSchema.KaspaSchnorr], + explorer: 'https://explorer.kaspa.org', + rpcUrls: [], + getTxLink: (txId: string) => { + if (typeof txId !== 'string') { + return '' + } + return `https://explorer.kaspa.org/txs/${txId}` + }, + getAddressLink: (address: string) => { + if (typeof address !== 'string') { + return '' + } + return `https://explorer.kaspa.org/addresses/${address}` + }, +}; +export const KaspaTestnet: ChainInfo = { + chainId: new ChainId(Chain.Kaspa, ChainNetwork.KaspaTestNet), + name: 'Kaspa Testnet', + fullName: 'Kaspa Testnet 10', + icon: '/chain-icons/Kaspa.svg', + nativeAssetSymbol: 'KAS', + nativeAssetDecimals: 8, + isMainnet: false, + isNativeGas: true, + ecosystem: Ecosystem.Kaspa, + supportedSignaturesSchemas: [WalletSignatureSchema.KaspaSchnorr], + explorer: 'https://explorer-tn10.kaspa.org/', + rpcUrls: [], + getTxLink: (txId: string) => { + if (typeof txId !== 'string') { + return '' + } + return `https://explorer-tn10.kaspa.org/txs/${txId}` + }, + getAddressLink: (address: string) => { + if (typeof address !== 'string') { + return '' + } + return `https://explorer-tn10.kaspa.org/addresses/${address}` + }, +}; diff --git a/packages/coin-kaspa/src/chain-wallet/index.ts b/packages/coin-kaspa/src/chain-wallet/index.ts new file mode 100644 index 00000000..10dab0e7 --- /dev/null +++ b/packages/coin-kaspa/src/chain-wallet/index.ts @@ -0,0 +1,2 @@ +export * from './chain' +export * from './wallet' diff --git a/packages/coin-kaspa/src/chain-wallet/utils.ts b/packages/coin-kaspa/src/chain-wallet/utils.ts new file mode 100644 index 00000000..f283c306 --- /dev/null +++ b/packages/coin-kaspa/src/chain-wallet/utils.ts @@ -0,0 +1,38 @@ +import { GeneratorSettings, SignableTransaction, GeneratorSummary, Generator, RpcUtxosByAddressesEntry, UtxoEntryReference, Address, TransactionOutpoint, Hash, ScriptPublicKey, KaspaNetwork, NetworkId, NetworkType } from ".." + +export const createTransactions = (settings: GeneratorSettings): { + transactions: SignableTransaction[] + summary: GeneratorSummary +} => { + const generator = new Generator(settings) + const transactions = [] + while (true) { + const tx: SignableTransaction | undefined = generator.generateTransaction() + if (tx) { + transactions.push(tx) + } else { + break + } + } + const summary = generator.summary() + return { + transactions, + summary + } +} + +export const rpcUtxosToUtxoEntries = (utxos: RpcUtxosByAddressesEntry[]): UtxoEntryReference[] => { + return utxos.map((utxo) => new UtxoEntryReference( + Address.fromString(utxo.address), + new TransactionOutpoint(Hash.fromString(utxo.outpoint!.transactionId), utxo.outpoint!.index), + BigInt(utxo.utxoEntry?.amount ?? 0), + ScriptPublicKey.fromHex(utxo.utxoEntry!.scriptPublicKey!), + BigInt(utxo.utxoEntry?.blockDaaScore ?? 0), + utxo.utxoEntry?.isCoinbase ?? false, + )) +} + +export const kaspaNetworkToNetworkId = (network: KaspaNetwork): NetworkId => { + const isMainnet = network === 'mainnet' + return new NetworkId(isMainnet ? NetworkType.Mainnet : NetworkType.Testnet, isMainnet ? undefined : 10) +} diff --git a/packages/coin-kaspa/src/chain-wallet/wallet.ts b/packages/coin-kaspa/src/chain-wallet/wallet.ts new file mode 100644 index 00000000..1b15063d --- /dev/null +++ b/packages/coin-kaspa/src/chain-wallet/wallet.ts @@ -0,0 +1,305 @@ +import BigNumber from 'bignumber.js'; +import { AssetInfo, BaseChainWallet, Chain, ChainAssetType, ChainInfo, WalletAccount } from '@delandlabs/coin-base' +import { + Address, + Encoding, + Fees, + GeneratorSettings, + Hash, + KaspaNetwork, + KaspaRpc, + kaspaToSompi, + Keypair, + NetworkId, + SendKasParams, + SendKrc20Params +} from '..'; +import { HDNodeWallet } from 'ethers'; +import { + createTransactions, + kaspaNetworkToNetworkId, + rpcUtxosToUtxoEntries +} from './utils'; + +const DERIVING_PATH = "m/44'/111111'/0'/0/0"; +const AMOUNT_FOR_INSCRIBE = kaspaToSompi('0.3'); + +export class KaspaChainWallet extends BaseChainWallet { + private network: KaspaNetwork; + private networkId: NetworkId; + private rpcClient: KaspaRpc; + private keyPair: Keypair; + private encoding: Encoding = Encoding.JSON; + + constructor(chainInfo: ChainInfo, phrase: string) { + if (!chainInfo.chainId.type.equals(Chain.Kaspa)) { + throw new Error('Kaspa: invalid chain type'); + } + super(chainInfo, phrase); + this.network = chainInfo.isMainnet ? 'mainnet' : 'testnet-10'; + this.networkId = kaspaNetworkToNetworkId(this.network); + const endpoint = this.network === 'mainnet' + ? import.meta.env.VITE_HIBIT_KASPA_MAINNET_ENDPOINT + : import.meta.env.VITE_HIBIT_KASPA_TESTNET_ENDPOINT; + this.rpcClient = new KaspaRpc( + this.networkId, + this.encoding, + endpoint, // ! TEMP: use endpoint for now + ); + const hdWallet = HDNodeWallet.fromPhrase(phrase, undefined, DERIVING_PATH); + const privKey = hdWallet.privateKey; + this.keyPair = Keypair.fromPrivateKeyHex(privKey.slice(2)); + console.debug(privKey, this.keyPair); + } + + public override getAccount: () => Promise = async () => { + return { + address: this.keyPair.toAddress(this.networkId.networkType).toString(), + publicKey: this.keyPair.publicKey + }; + }; + + public override signMessage: (message: string) => Promise = async ( + message + ) => { + const signature = this.keyPair.signMessageWithAuxData( + Buffer.from(message), + new Uint8Array(32).fill(0) + ); + return Buffer.from(signature).toString('hex'); + }; + + public override balanceOf = async (address: string, assetInfo: AssetInfo) => { + if (!assetInfo.chain.equals(Chain.Kaspa)) { + throw new Error('Kaspa: invalid asset chain'); + } + // native + if (assetInfo.chainAssetType.equals(ChainAssetType.Native)) { + try { + const balance = await this.rpcClient.getBalance(address); + return new BigNumber(balance).shiftedBy(-assetInfo.decimalPlaces.value); + } + catch (e) { + console.error(e); + return new BigNumber(0); + } + } + // krc20 + if (assetInfo.chainAssetType.equals(ChainAssetType.KRC20)) { + const balanceInfo = await this.rpcClient.getKrc20Balance( + address, + assetInfo.contractAddress + ); + return balanceInfo + ? new BigNumber(balanceInfo.balance).shiftedBy(-Number(balanceInfo.dec)) + : new BigNumber(0); + } + + throw new Error( + `Kaspa: unsupported chain asset type ${assetInfo.chainAssetType.toString()}` + ); + }; + + public override transfer = async ( + toAddress: string, + amount: BigNumber, + assetInfo: AssetInfo + ): Promise => { + if (!assetInfo.chain.equals(Chain.Kaspa)) { + throw new Error('Kaspa: invalid asset chain'); + } + try { + // native + if (assetInfo.chainAssetType.equals(ChainAssetType.Native)) { + const sendParam = new SendKasParams( + this.keyPair.toAddress(this.networkId.networkType), + BigInt(amount.shiftedBy(assetInfo.decimalPlaces.value).toString()), + Address.fromString(toAddress), + this.networkId, + new Fees(0n) + ); + const { + result: { transactions, summary } + } = await this.createTransactionsByOutputs(sendParam); + for (const tx of transactions) { + const signedTx = tx.sign([this.keyPair.privateKey!]); + const reqMessage = signedTx.toSubmitableJson(); + await this.rpcClient.submitTransaction({ + transaction: reqMessage as any, + allowOrphan: false + }); + } + return summary.finalTransactionId?.toString() ?? ''; + } + // krc20 + if (assetInfo.chainAssetType.equals(ChainAssetType.KRC20)) { + // inscribe transactions + const sendKrc20Param = new SendKrc20Params( + this.keyPair.toAddress(this.networkId.networkType), + BigInt(amount.shiftedBy(assetInfo.decimalPlaces.value).toString()), + toAddress, + assetInfo.contractAddress, + this.networkId, + AMOUNT_FOR_INSCRIBE, + new Fees(0n) + ); + const { + result: { transactions: commitTxs } + } = await this.createTransactionsByOutputs(sendKrc20Param); + let commitTxId = ''; + for (const commitTx of commitTxs) { + const signedTx = commitTx.sign([this.keyPair.privateKey!]); + const reqMessage = signedTx.toSubmitableJson(); + commitTxId = await this.rpcClient.submitTransaction({ + transaction: reqMessage as any, + allowOrphan: false + }); + } + console.log('commitTxId', commitTxId); + + const { + result: { transactions: revealTxs } + } = await this.createTransactionsByOutputs(sendKrc20Param, commitTxId); + let revealTxId = ''; + for (const revealTx of revealTxs) { + // sign + const signedTx = revealTx.sign([this.keyPair.privateKey!], false); + const ourOutput = signedTx.transaction.tx.inputs.findIndex( + (input) => Buffer.from(input.signatureScript).toString('hex') === '' + ); + if (ourOutput !== -1) { + const signature = signedTx.transaction.createInputSignature( + ourOutput, + this.keyPair.privateKey! + ); + const encodedSignature = + sendKrc20Param.script.encodePayToScriptHashSignatureScript( + signature + ); + signedTx.transaction.fillInputSignature( + ourOutput, + encodedSignature + ); + } + const reqMessage = signedTx.toSubmitableJson(); + console.log('reqMessage', reqMessage); + revealTxId = await this.rpcClient.submitTransaction({ + transaction: reqMessage as any, + allowOrphan: false + }); + } + console.log('revealTxId', revealTxId); + + return revealTxId; + } + } catch (e) { + console.error(e); + // TODO: handle error + throw e; + } + + throw new Error( + `Kaspa: unsupported chain asset type ${assetInfo.chainAssetType.toString()}` + ); + }; + + public override getEstimatedFee = async ( + toAddress: string, + amount: BigNumber, + assetInfo: AssetInfo + ): Promise => { + if (!assetInfo.chain.equals(Chain.Kaspa)) { + throw new Error('Kaspa: invalid asset chain'); + } + // native + if (assetInfo.chainAssetType.equals(ChainAssetType.Native)) { + const sendKasParam = new SendKasParams( + this.keyPair.toAddress(this.networkId.networkType), + BigInt(amount.shiftedBy(assetInfo.decimalPlaces.value).toString()), + Address.fromString(toAddress), + this.networkId, + new Fees(0n) + ); + const { priorityFee } = + await this.createTransactionsByOutputs(sendKasParam); + return new BigNumber(priorityFee.amount.toString()).shiftedBy( + -assetInfo.decimalPlaces.value + ); + } + // krc20 + if (assetInfo.chainAssetType.equals(ChainAssetType.KRC20)) { + const sendKrc20Param = new SendKrc20Params( + this.keyPair.toAddress(this.networkId.networkType), + BigInt(amount.shiftedBy(assetInfo.decimalPlaces.value).toString()), + toAddress, + assetInfo.contractAddress, + this.networkId, + AMOUNT_FOR_INSCRIBE, + new Fees(0n) + ); + const { priorityFee } = + await this.createTransactionsByOutputs(sendKrc20Param); + return new BigNumber(priorityFee.amount.toString()).shiftedBy( + -this.chainInfo.nativeAssetDecimals + ); + } + + throw new Error( + `Kaspa: unsupported chain asset type ${assetInfo.chainAssetType.toString()}` + ); + }; + + private createTransactionsByOutputs = async ( + sendParam: SendKasParams | SendKrc20Params, + commitTxId?: string + ): Promise<{ + priorityFee: Fees; + result: ReturnType; + }> => { + const isKrc20Tx = sendParam instanceof SendKrc20Params; + const isReveal = commitTxId !== undefined; + if (!isKrc20Tx && isReveal) { + throw new Error('Kaspa: invalid sendParam'); + } + + const utxos = await this.rpcClient.getUtxosByAddress( + sendParam.sender.toString() + ); + console.log( + 'utxos', + utxos.map((utxo) => utxo.outpoint?.transactionId), + utxos + ); + const utxoEntries = rpcUtxosToUtxoEntries(utxos); + const settings: GeneratorSettings = !isKrc20Tx + ? (sendParam as SendKasParams).toGeneratorSettings(utxoEntries) + : !isReveal + ? (sendParam as SendKrc20Params).toCommitTxGeneratorSettings( + utxoEntries + ) + : (sendParam as SendKrc20Params).toRevealTxGeneratorSettings( + utxoEntries, + Hash.fromHex(commitTxId) + ); + const txResult = createTransactions(settings); + if (sendParam.priorityFee?.amount) { + return { + priorityFee: sendParam.priorityFee, + result: txResult + }; + } + // calculate fee if priorityFee is not set + // and return actual transactions with calculated fee + const feeSetting = await this.rpcClient.getFeeEstimate(); + const mass = + txResult.transactions[txResult.transactions.length - 1].tx.mass; + const sompiFee = mass * BigInt(feeSetting?.priorityBucket?.feerate ?? 1n); + const txResultWithFee = createTransactions( + settings.setPriorityFee(new Fees(sompiFee)) + ); + return { + priorityFee: new Fees(sompiFee), + result: txResultWithFee + }; + }; +} diff --git a/packages/coin-kaspa/src/index.ts b/packages/coin-kaspa/src/index.ts index 273c9a12..2360da1b 100644 --- a/packages/coin-kaspa/src/index.ts +++ b/packages/coin-kaspa/src/index.ts @@ -3,3 +3,4 @@ export type * from './compiled_proto/rpc'; export * from './rpc'; export * from './lib'; export type { TransactionId, TransactionMass } from './lib'; +export * from './chain-wallet' diff --git a/packages/coin-kaspa/src/lib/index.ts b/packages/coin-kaspa/src/lib/index.ts index d424346c..fa45f8d5 100644 --- a/packages/coin-kaspa/src/lib/index.ts +++ b/packages/coin-kaspa/src/lib/index.ts @@ -5,5 +5,5 @@ export * from './consensus'; export { Keypair } from './keypair'; export { kaspaToSompi, addressFromScriptPublicKey } from './utils'; export * from './resolver'; -export { SendKasPramas, SendKrc20Pramas } from './send-param'; +export { SendKasParams, SendKrc20Params } from './send-param'; export type { TransactionId, TransactionMass } from './tx'; diff --git a/packages/coin-kaspa/src/lib/send-param.ts b/packages/coin-kaspa/src/lib/send-param.ts index 88ab516c..239d8f77 100644 --- a/packages/coin-kaspa/src/lib/send-param.ts +++ b/packages/coin-kaspa/src/lib/send-param.ts @@ -7,7 +7,7 @@ import { NetworkId } from './consensus'; /** * Interface representing parameters for sending KRC-20 tokens. */ -export interface ISendKrc20Pramas { +export interface ISendKrc20Params { /** * Sets the priority fee for the transaction. * @param priorityFee - The priority fee to set. @@ -18,7 +18,7 @@ export interface ISendKrc20Pramas { /** * Class representing parameters for sending Kaspa. */ -class SendKasPramas implements ISendKrc20Pramas { +class SendKasParams implements ISendKrc20Params { sender: Address; amount: bigint; receiver: Address; @@ -65,7 +65,7 @@ class SendKasPramas implements ISendKrc20Pramas { /** * Class representing parameters for sending KRC-20 tokens. */ -class SendKrc20Pramas implements ISendKrc20Pramas { +class SendKrc20Params implements ISendKrc20Params { sender: Address; krc20Amount: bigint; receiver: Address; @@ -173,4 +173,4 @@ class SendKrc20Pramas implements ISendKrc20Pramas { } } -export { SendKasPramas, SendKrc20Pramas }; +export { SendKasParams, SendKrc20Params }; diff --git a/packages/coin-kaspa/tests/tx/generator-kas.test.ts b/packages/coin-kaspa/tests/tx/generator-kas.test.ts index d6754d53..154ff2d2 100644 --- a/packages/coin-kaspa/tests/tx/generator-kas.test.ts +++ b/packages/coin-kaspa/tests/tx/generator-kas.test.ts @@ -1,6 +1,6 @@ import { describe, expect, it } from 'vitest'; import { Fees, Generator, SignableTransaction } from '../../src/lib/tx'; -import { kaspaToSompi, NetworkId, NetworkType, SendKasPramas } from '../../src/lib'; +import { kaspaToSompi, NetworkId, NetworkType, SendKasParams } from '../../src/lib'; import { parseTxsFromFile, parseUtxosFromFile } from './test-helper'; const SENDER_ADDR = 'kaspatest:qzzzvv57j68mcv3rsd2reshhtv4rcw4xc8snhenp2k4wu4l30jfjxlgfr8qcz'; @@ -9,9 +9,9 @@ const TESTNET_10 = new NetworkId(NetworkType.Testnet, 10); const PRIORITY_FEES = new Fees(kaspaToSompi(0.02)); describe('Generator kas tx', () => { - const sentKas10 = new SendKasPramas(SENDER_ADDR, kaspaToSompi(10), RECEIVER_ADDR, TESTNET_10, PRIORITY_FEES); - const send1Kas10K = new SendKasPramas(SENDER_ADDR, kaspaToSompi(10000), RECEIVER_ADDR, TESTNET_10, PRIORITY_FEES); - const sendKas1M = new SendKasPramas(SENDER_ADDR, kaspaToSompi(1000000), RECEIVER_ADDR, TESTNET_10, PRIORITY_FEES); + const sentKas10 = new SendKasParams(SENDER_ADDR, kaspaToSompi(10), RECEIVER_ADDR, TESTNET_10, PRIORITY_FEES); + const send1Kas10K = new SendKasParams(SENDER_ADDR, kaspaToSompi(10000), RECEIVER_ADDR, TESTNET_10, PRIORITY_FEES); + const sendKas1M = new SendKasParams(SENDER_ADDR, kaspaToSompi(1000000), RECEIVER_ADDR, TESTNET_10, PRIORITY_FEES); const testCases = [ { name: '10 KAS', params: sentKas10 }, { name: '10K KAS', params: send1Kas10K }, diff --git a/packages/coin-kaspa/tests/tx/generator-krc20.test.ts b/packages/coin-kaspa/tests/tx/generator-krc20.test.ts index abad8eba..369403c3 100644 --- a/packages/coin-kaspa/tests/tx/generator-krc20.test.ts +++ b/packages/coin-kaspa/tests/tx/generator-krc20.test.ts @@ -1,6 +1,6 @@ import { describe, expect, it } from 'vitest'; import { Fees, Generator, SignableTransaction } from '../../src/lib/tx'; -import { kaspaToSompi, NetworkId, NetworkType, SendKrc20Pramas } from '../../src/lib'; +import { kaspaToSompi, NetworkId, NetworkType, SendKrc20Params } from '../../src/lib'; import { parseTxsFromFile, parseUtxosFromFile } from './test-helper'; import { SignedType } from '../../src/lib/tx/generator/model/signed-tx'; @@ -12,7 +12,7 @@ const PRIORITY_FEES = new Fees(kaspaToSompi(0.02)); const OUTPUT_AMOUNT = kaspaToSompi(0.3); describe('Generator kas tx', () => { - const sentKrc20CommitTx = new SendKrc20Pramas( + const sentKrc20CommitTx = new SendKrc20Params( SENDER_ADDR, kaspaToSompi(101), RECEIVER_ADDR, diff --git a/packages/coin-solana/.gitignore b/packages/coin-solana/.gitignore new file mode 100644 index 00000000..a547bf36 --- /dev/null +++ b/packages/coin-solana/.gitignore @@ -0,0 +1,24 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +dist +dist-ssr +*.local + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +.DS_Store +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? diff --git a/packages/coin-solana/.prettierignore b/packages/coin-solana/.prettierignore new file mode 100644 index 00000000..bfe3b8d3 --- /dev/null +++ b/packages/coin-solana/.prettierignore @@ -0,0 +1 @@ +tsconfig.json \ No newline at end of file diff --git a/packages/coin-solana/package.json b/packages/coin-solana/package.json new file mode 100644 index 00000000..8818d0f7 --- /dev/null +++ b/packages/coin-solana/package.json @@ -0,0 +1,47 @@ +{ + "name": "@delandlabs/coin-solana", + "private": false, + "version": "0.0.0", + "type": "module", + "files": [ + "dist" + ], + "main": "./dist/coin-solana.umd.cjs", + "module": "./dist/coin-solana.js", + "types": "dist/index.d.ts", + "exports": { + ".": { + "import": { + "types": "./dist/index.d.ts", + "default": "./dist/coin-solana.js" + }, + "require": { + "types": "./dist/index.d.ts", + "default": "./dist/coin-solana.umd.cjs" + } + } + }, + "scripts": { + "dev": "vite", + "test": "vitest", + "build": "vite build", + "lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0", + "format": "prettier --write ." + }, + "dependencies": { + "@delandlabs/coin-base": "*", + "@solana/web3.js": "^1.94.0" + }, + "devDependencies": { + "@eslint/js": "^9.16.0", + "@rollup/plugin-typescript": "^12.1.1", + "@typescript-eslint/eslint-plugin": "^8.16.0", + "@typescript-eslint/parser": "^8.16.0", + "eslint": "^9.16.0", + "globals": "^15.12.0", + "typescript": "~5.6.2", + "typescript-eslint": "^8.16.0", + "vite": "^6.0.1", + "vitest": "^2.1.6" + } +} diff --git a/packages/coin-solana/src/chain-wallet/chain.ts b/packages/coin-solana/src/chain-wallet/chain.ts new file mode 100644 index 00000000..5674d3ea --- /dev/null +++ b/packages/coin-solana/src/chain-wallet/chain.ts @@ -0,0 +1,33 @@ +import { ChainInfo, ChainId, Chain, ChainNetwork, Ecosystem, WalletSignatureSchema } from "@delandlabs/coin-base"; +import { clusterApiUrl } from '@solana/web3.js'; + +export const Solana: ChainInfo = { + chainId: new ChainId(Chain.Solana, ChainNetwork.SolanaMainNet), + name: 'Solana', + fullName: 'Solana Mainnet', + icon: '/chain-icons/Solana.svg', + nativeAssetSymbol: 'SOL', + nativeAssetDecimals: 9, + isMainnet: true, + isNativeGas: true, + ecosystem: Ecosystem.Solana, + supportedSignaturesSchemas: [WalletSignatureSchema.SolanaEddsa], + explorer: 'https://explorer.solana.com', + rpcUrls: [clusterApiUrl('mainnet-beta')], + caseSensitiveAddress: true +}; +export const SolanaTestnet: ChainInfo = { + chainId: new ChainId(Chain.Solana, ChainNetwork.SolanaTestNet), + name: 'SolanaTestnet', + fullName: 'Solana Testnet', + icon: '/chain-icons/Solana.svg', + nativeAssetSymbol: 'SOL', + nativeAssetDecimals: 9, + isMainnet: false, + isNativeGas: true, + ecosystem: Ecosystem.Solana, + supportedSignaturesSchemas: [WalletSignatureSchema.SolanaEddsa], + explorer: 'https://explorer.solana.com?cluster=testnet', + rpcUrls: [clusterApiUrl('testnet')], + caseSensitiveAddress: true +}; diff --git a/packages/coin-solana/src/chain-wallet/index.ts b/packages/coin-solana/src/chain-wallet/index.ts new file mode 100644 index 00000000..10dab0e7 --- /dev/null +++ b/packages/coin-solana/src/chain-wallet/index.ts @@ -0,0 +1,2 @@ +export * from './chain' +export * from './wallet' diff --git a/packages/coin-solana/src/chain-wallet/wallet.ts b/packages/coin-solana/src/chain-wallet/wallet.ts new file mode 100644 index 00000000..e69de29b diff --git a/packages/coin-solana/src/index.ts b/packages/coin-solana/src/index.ts new file mode 100644 index 00000000..02d3efed --- /dev/null +++ b/packages/coin-solana/src/index.ts @@ -0,0 +1 @@ +export * from './chain-wallet' diff --git a/packages/coin-solana/src/vite-env.d.ts b/packages/coin-solana/src/vite-env.d.ts new file mode 100644 index 00000000..11f02fe2 --- /dev/null +++ b/packages/coin-solana/src/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/packages/coin-solana/tsconfig.json b/packages/coin-solana/tsconfig.json new file mode 100644 index 00000000..f48fcfc8 --- /dev/null +++ b/packages/coin-solana/tsconfig.json @@ -0,0 +1,12 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "baseUrl": ".", + "paths": { + "src/*": ["src/*"] + }, + "experimentalDecorators": true, + }, + "include": ["src"], + "exclude": ["**/node_modules"] +} diff --git a/packages/coin-solana/vite.config.ts b/packages/coin-solana/vite.config.ts new file mode 100644 index 00000000..5910ffb7 --- /dev/null +++ b/packages/coin-solana/vite.config.ts @@ -0,0 +1,38 @@ +import { defineConfig } from 'vite'; +import { resolve } from 'path'; +import typescript from '@rollup/plugin-typescript'; + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [], + resolve: { + alias: { + src: resolve(__dirname, 'src') + } + }, + build: { + lib: { + // Could also be a dictionary or array of multiple entry points + entry: resolve(__dirname, 'src/index.ts'), + name: 'CoinSolana', + // the proper extensions will be added + fileName: 'coin-solana' + }, + commonjsOptions: { + transformMixedEsModules: true, + include: [/node_modules/] + }, + rollupOptions: { + plugins: [ + typescript({ + target: 'es2020', + rootDir: resolve(__dirname, 'src'), + declaration: true, + declarationDir: resolve(__dirname, 'dist'), + exclude: [resolve(__dirname, 'node_modules/**'), resolve(__dirname, 'test/**')], + allowSyntheticDefaultImports: true + }) + ] + } + } +}); diff --git a/packages/coin-ton/.gitignore b/packages/coin-ton/.gitignore new file mode 100644 index 00000000..a547bf36 --- /dev/null +++ b/packages/coin-ton/.gitignore @@ -0,0 +1,24 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +dist +dist-ssr +*.local + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +.DS_Store +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? diff --git a/packages/coin-ton/.prettierignore b/packages/coin-ton/.prettierignore new file mode 100644 index 00000000..bfe3b8d3 --- /dev/null +++ b/packages/coin-ton/.prettierignore @@ -0,0 +1 @@ +tsconfig.json \ No newline at end of file diff --git a/packages/coin-ton/package.json b/packages/coin-ton/package.json new file mode 100644 index 00000000..2e125dda --- /dev/null +++ b/packages/coin-ton/package.json @@ -0,0 +1,54 @@ +{ + "name": "@delandlabs/coin-ton", + "private": false, + "version": "0.0.0", + "type": "module", + "files": [ + "dist" + ], + "main": "./dist/coin-ton.umd.cjs", + "module": "./dist/coin-ton.js", + "types": "dist/index.d.ts", + "exports": { + ".": { + "import": { + "types": "./dist/index.d.ts", + "default": "./dist/coin-ton.js" + }, + "require": { + "types": "./dist/index.d.ts", + "default": "./dist/coin-ton.umd.cjs" + } + } + }, + "scripts": { + "dev": "vite", + "test": "vitest", + "build": "vite build", + "lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0", + "format": "prettier --write ." + }, + "dependencies": { + "@delandlabs/coin-base": "*", + "@openproduct/web-sdk": "^0.23.0", + "@orbs-network/ton-access": "^2.3.3", + "@ton/core": "^0.56.3", + "@ton/crypto": "^3.3.0", + "@ton/ton": "^14.0.0", + "tonweb": "^0.0.66", + "tonweb-mnemonic": "^1.0.1", + "tweetnacl": "^1.0.3" + }, + "devDependencies": { + "@eslint/js": "^9.16.0", + "@rollup/plugin-typescript": "^12.1.1", + "@typescript-eslint/eslint-plugin": "^8.16.0", + "@typescript-eslint/parser": "^8.16.0", + "eslint": "^9.16.0", + "globals": "^15.12.0", + "typescript": "~5.6.2", + "typescript-eslint": "^8.16.0", + "vite": "^6.0.1", + "vitest": "^2.1.6" + } +} diff --git a/packages/coin-ton/src/chain-wallet/chain.ts b/packages/coin-ton/src/chain-wallet/chain.ts new file mode 100644 index 00000000..36a81c1e --- /dev/null +++ b/packages/coin-ton/src/chain-wallet/chain.ts @@ -0,0 +1,116 @@ +import { ChainInfo, ChainId, Chain, ChainNetwork, Ecosystem, WalletSignatureSchema } from "@delandlabs/coin-base"; +import { getHttpEndpoint } from "@orbs-network/ton-access"; +import TonWeb from 'tonweb' + +export const Ton: ChainInfo = { + chainId: new ChainId(Chain.Ton, ChainNetwork.TonMainNet), + name: 'TON', + fullName: 'The Open Mask', + icon: '/chain-icons/Ton.svg', + nativeAssetSymbol: 'TON', + nativeAssetDecimals: 9, + isMainnet: true, + isNativeGas: true, + ecosystem: Ecosystem.Ton, + supportedSignaturesSchemas: [WalletSignatureSchema.TonEddsaOpenMask], + explorer: 'https://tonviewer.com', + rpcUrls: [], + caseSensitiveAddress: true, + getServerFormatAddress: (address: string): string | null => { + try { + return new TonWeb.utils.Address(address).toString( + false, + undefined, + undefined, + false + ); + } catch (e) { + return null; + } + }, + getTxLink: (txId: string) => { + if (!txId) { + return ''; + } + let hexTxId = txId; + try { + hexTxId = Buffer.from(txId, 'base64').toString('hex'); + } catch (e) { + console.error(e); + } + return `https://tonviewer.com/transaction/${hexTxId}`; + }, + getAddressLink: (address: string) => { + try { + const bouncable = new TonWeb.utils.Address(address).toString( + true, + true, + true, + false + ); + return `https://tonviewer.com/${bouncable}`; + } catch (e) { + return address; + } + } +}; +export const TonTestnet: ChainInfo = { + chainId: new ChainId(Chain.Ton, ChainNetwork.TonTestNet), + name: 'TON Testnet', + fullName: 'The Open Mask Testnet', + icon: '/chain-icons/Ton.svg', + nativeAssetSymbol: 'TON', + nativeAssetDecimals: 9, + isMainnet: false, + isNativeGas: true, + ecosystem: Ecosystem.Ton, + supportedSignaturesSchemas: [WalletSignatureSchema.TonEddsaOpenMask], + explorer: 'https://testnet.tonviewer.com', + rpcUrls: [], + caseSensitiveAddress: true, + getServerFormatAddress: (address: string): string | null => { + try { + return new TonWeb.utils.Address(address).toString( + false, + undefined, + undefined, + true + ); + } catch (e) { + return null; + } + }, + getTxLink: (txId: string) => { + if (!txId) { + return ''; + } + let hexTxId = txId; + try { + hexTxId = Buffer.from(txId, 'base64').toString('hex'); + } catch (e) { + console.error(e); + } + return `https://testnet.tonviewer.com/transaction/${hexTxId}`; + }, + getAddressLink: (address: string) => { + try { + const bouncable = new TonWeb.utils.Address(address).toString( + true, + true, + true, + false + ); + return `https://testnet.tonviewer.com/${bouncable}`; + } catch (e) { + return address; + } + } +}; +(async () => { + const [tonMainEndpoint, tonTestEndpoint] = await Promise.all([ + getHttpEndpoint(), + getHttpEndpoint({ network: 'testnet' }) + ]); + Ton.rpcUrls.push(tonMainEndpoint); + TonTestnet.rpcUrls.push(tonTestEndpoint); +})(); diff --git a/packages/coin-ton/src/chain-wallet/index.ts b/packages/coin-ton/src/chain-wallet/index.ts new file mode 100644 index 00000000..10dab0e7 --- /dev/null +++ b/packages/coin-ton/src/chain-wallet/index.ts @@ -0,0 +1,2 @@ +export * from './chain' +export * from './wallet' diff --git a/packages/coin-ton/src/chain-wallet/utils.ts b/packages/coin-ton/src/chain-wallet/utils.ts new file mode 100644 index 00000000..cbfd5638 --- /dev/null +++ b/packages/coin-ton/src/chain-wallet/utils.ts @@ -0,0 +1,12 @@ +import { ChainId, ChainInfo } from '@delandlabs/coin-base'; +import * as TonChains from './chain' + +export function getChain(chainId: ChainId | null): ChainInfo | null { + if (!chainId) return null; + const chains = Object.values(TonChains) + return chains.find(c => c.chainId.equals(chainId)) ?? null; +} + +export const sleep = (ms: number) => { + return new Promise(resolve => setTimeout(resolve, ms)); +} diff --git a/packages/coin-ton/src/chain-wallet/wallet.ts b/packages/coin-ton/src/chain-wallet/wallet.ts new file mode 100644 index 00000000..eee1967a --- /dev/null +++ b/packages/coin-ton/src/chain-wallet/wallet.ts @@ -0,0 +1,338 @@ +import BigNumber from "bignumber.js"; +import { Buffer } from 'buffer/'; +import { getHttpEndpoint } from "@orbs-network/ton-access"; +import { bytesToHex, hexToBytes } from '@openproduct/web-sdk'; +import { TonClient, WalletContractV4, internal, Address, toNano, fromNano, OpenedContract, JettonMaster, JettonWallet, beginCell, SendMode, Cell, StateInit, storeMessage } from '@ton/ton'; +import { KeyPair, mnemonicToPrivateKey } from "@ton/crypto"; +import { external, storeStateInit } from '@ton/core' +import nacl from "tweetnacl"; +import { BaseChainWallet, ChainInfo, Chain, AssetInfo, ChainAssetType, ChainNetwork, WalletAccount } from "@delandlabs/coin-base"; +import { TonConnectTransactionPayload, TonConnectSignDataPayload, TonConnectSignDataResult } from "../ton-connect"; +import { sleep } from "./utils"; + +const JETTON_TRANSFER_AMOUNT = new BigNumber(0.1) +const JETTON_FORWARD_AMOUNT = new BigNumber(0.0001) + +export class TonChainWallet extends BaseChainWallet { + private keyPair: KeyPair | null = null + private client: TonClient | null = null + private wallet: OpenedContract | null = null + private readyPromise: Promise + + constructor(chainInfo: ChainInfo, phrase: string) { + if (!chainInfo.chainId.type.equals(Chain.Ton)) { + throw new Error('Ton: invalid chain type'); + } + super(chainInfo, phrase) + this.readyPromise = new Promise((resolve) => { + this.initWallet(phrase).then(resolve) + }) + } + + public override getAccount: () => Promise = async () => { + await this.readyPromise + const address = this.wallet!.address + return { + address: address.toString({ + urlSafe: true, + bounceable: false, + testOnly: this.getIsTestNet(), + }), + publicKey: this.wallet!.publicKey.toString('hex'), + } + } + + // ref: OpenMask extension + public override signMessage: (message: string) => Promise = async (message) => { + if (!message) { + throw new Error('Ton: Missing sign data'); + } + await this.readyPromise + const valueHash = nacl.hash(Buffer.from(message, "utf8")); + /** + * According: https://github.com/ton-foundation/specs/blob/main/specs/wtf-0002.md + */ + if (valueHash.length + 'ton-safe-sign-magic'.length >= 127) { + throw new Error('Ton: Too large personal message'); + } + const hex = Buffer.concat([ + Buffer.from([0xff, 0xff]), + Buffer.from('ton-safe-sign-magic'), + valueHash, + ]).toString('hex'); + const signature = nacl.sign.detached(hexToBytes(hex), this.keyPair!.secretKey); + return bytesToHex(signature); + } + + public override balanceOf = async (address: string, assetInfo: AssetInfo) => { + try { + Address.parse(address) + } catch (e) { + throw new Error('Ton: invalid wallet address') + } + if (!assetInfo.chain.equals(Chain.Ton)) { + throw new Error('Ton: invalid asset chain'); + } + await this.readyPromise + + // native + if (assetInfo.chainAssetType.equals(ChainAssetType.Native)) { + const addr = Address.parse(address) + const balance = await this.client!.getBalance(addr); + return new BigNumber(fromNano(balance)) + } + // jetton + if (assetInfo.chainAssetType.equals(ChainAssetType.Jetton)) { + const jettonWallet = await this.getJettonWallet(address, assetInfo.contractAddress) + const balance = await jettonWallet.getBalance() + return new BigNumber(String(balance)).shiftedBy(-assetInfo.decimalPlaces.value) + } + + throw new Error(`Ton: unsupported chain asset type ${assetInfo.chainAssetType.toString()}`); + }; + + public override transfer = async (toAddress: string, amount: BigNumber, assetInfo: AssetInfo) => { + if (!assetInfo.chain.equals(Chain.Ton)) { + throw new Error('Ton: invalid asset chain'); + } + await this.readyPromise + + // native + if (assetInfo.chainAssetType.equals(ChainAssetType.Native)) { + const seqno = await this.wallet!.getSeqno() || 0; + await this.wallet!.sendTransfer({ + seqno: seqno, + secretKey: this.keyPair!.secretKey, + messages: [internal({ + value: toNano(amount.toString()), + to: Address.parse(toAddress), + })], + sendMode: SendMode.PAY_GAS_SEPARATELY + SendMode.IGNORE_ERRORS, + }); + // wait until confirmed + let currentSeqno = seqno; + while (currentSeqno == seqno) { + await sleep(3000); + currentSeqno = await this.wallet!.getSeqno() || 0; + } + return '' + } + // jetton + if (assetInfo.chainAssetType.equals(ChainAssetType.Jetton)) { + const ownerAddress = (await this.getAccount()).address + + // gas check + const gasBalance = await this.client!.getBalance(Address.parse(ownerAddress)); + const gasBn = new BigNumber(fromNano(gasBalance)) + const minGas = JETTON_TRANSFER_AMOUNT.plus(JETTON_FORWARD_AMOUNT) + if (gasBn.lt(minGas)) { + throw new Error(`Insufficient gas balance (at least ${minGas.toString()} Ton)`) + } + + const jettonWallet = await this.getJettonWallet(ownerAddress, assetInfo.contractAddress) + + const forwardPayload = beginCell() + .storeUint(0, 32) // 0 opcode means we have a comment + .storeStringTail('Jetton') + .endCell(); + + const messageBody = beginCell() + .storeUint(0x0f8a7ea5, 32) // opcode for jetton transfer + .storeUint(0, 64) // query id + .storeCoins(BigInt(amount.shiftedBy(assetInfo.decimalPlaces.value).toString())) // jetton amount + .storeAddress(Address.parse(toAddress)) + .storeAddress(Address.parse(ownerAddress)) // response destination + .storeBit(0) // no custom payload + .storeCoins(toNano(JETTON_FORWARD_AMOUNT.toString())) // forward amount - if >0, will send notification message + .storeBit(1) // we store forwardPayload as a reference + .storeRef(forwardPayload) + .endCell(); + + const internalMessage = internal({ + to: jettonWallet.address, + value: toNano(JETTON_TRANSFER_AMOUNT.toString()), + bounce: true, + body: messageBody, + }); + + // send jetton + const seqno = await this.wallet!.getSeqno() || 0; + try { + await this.wallet!.sendTransfer({ + seqno: seqno, + secretKey: this.keyPair!.secretKey, + messages: [internalMessage], + sendMode: SendMode.PAY_GAS_SEPARATELY + SendMode.IGNORE_ERRORS, + }) + // wait until confirmed + let currentSeqno = seqno; + while (currentSeqno == seqno) { + await sleep(3000); + currentSeqno = await this.wallet!.getSeqno() || 0; + } + return '' + } catch (e: any) { + if (e.response?.status === 500) { + const message: string = e.response?.data?.error || '' + if (/^LITE_SERVER_UNKNOWN:[.\s\S]*inbound external message rejected by transaction[.\s\S]*$/i.test(message)) { + throw new Error(`Insufficient gas balance (at least ${minGas} Ton)`) + } + } + throw e + } + } + + throw new Error(`Ton: unsupported chain asset type ${assetInfo.chainAssetType.toString()}`); + } + + public override getEstimatedFee = async (toAddress: string, amount: BigNumber, assetInfo: AssetInfo): Promise => { + if (!assetInfo.chain.equals(Chain.Ton)) { + throw new Error('Ton: invalid asset chain'); + } + await this.readyPromise + const ownerAddress = (await this.getAccount()).address + + // native + if (assetInfo.chainAssetType.equals(ChainAssetType.Native)) { + const body = internal({ + value: toNano(amount.toString()), + to: Address.parse(toAddress), + }).body + const feeData = await this.client?.estimateExternalMessageFee( + Address.parse(ownerAddress), + { + body, + initCode: null, + initData: null, + ignoreSignature: true, + } + ) + if (!feeData) { + throw new Error('Ton: failed to estimate fee') + } + const fee = fromNano( + String( + feeData.source_fees.fwd_fee + + feeData.source_fees.in_fwd_fee + + feeData.source_fees.storage_fee + + feeData.source_fees.gas_fee + ) + ); + return new BigNumber(fee) + } + + // jetton + if (assetInfo.chainAssetType.equals(ChainAssetType.Jetton)) { + const minGas = JETTON_TRANSFER_AMOUNT.plus(JETTON_FORWARD_AMOUNT) + return minGas + } + + throw new Error(`Ton: unsupported chain asset type ${assetInfo.chainAssetType.toString()}`); + } + + public tonConnectGetStateInit = (): string => { + const stateInit = beginCell() + .storeWritable(storeStateInit(this.wallet!.init)) + .endCell(); + const base64 = stateInit + .toBoc({ idx: true, crc32: true }) + .toString("base64") + return base64 + } + + public tonConnectTransfer = async (payload: TonConnectTransactionPayload): Promise => { + const seqno = await this.wallet!.getSeqno() || 0; + const transfer = await this.createTonConnectTransfer(seqno, payload) + await this.wallet!.send(transfer) + const externalMessage = beginCell() + .storeWritable( + storeMessage( + external({ + to: this.wallet!.address, + init: seqno === 0 ? this.wallet!.init : undefined, + body: transfer, + }) + ) + ) + .endCell() + .toBoc({ idx: false }) + .toString("base64") + return externalMessage + } + + public tonConnectSignData = async (payload: TonConnectSignDataPayload): Promise => { + const timestamp = Date.now() / 1000 + const X: Cell = Cell.fromBase64(payload.cell) // Payload cell + const prefix = Buffer.alloc(4 + 8); // version + timestamp + prefix.writeUInt32BE(payload.schema_crc, 0); + prefix.writeBigUInt64BE(timestamp, 4); + const signature = nacl.sign.detached(Buffer.concat([prefix, X.hash()]), this.keyPair!.secretKey); + return { + signature: bytesToHex(signature), + timestamp: timestamp.toString(), + } + } + + private initWallet = async (phrase: string) => { + const endpoint = await getHttpEndpoint({ + network: this.getIsTestNet() ? 'testnet' : 'mainnet', + }) + this.client = new TonClient({ endpoint }); + const mnemonic = phrase; // your 24 secret words (replace ... with the rest of the words) + this.keyPair = await mnemonicToPrivateKey(mnemonic.split(' ')); + this.wallet = this.client.open( + WalletContractV4.create({ + workchain: 0, + publicKey: this.keyPair.publicKey, + }) + ); + } + + private getIsTestNet = () => { + return this.chainInfo.chainId.network.equals(ChainNetwork.TonTestNet) + } + + private getAddressBounceable = (address: string) => { + return Address.isFriendly(address) + ? Address.parseFriendly(address).isBounceable + : false; + } + + private toStateInit = (stateInit?: string): StateInit | undefined => { + if (!stateInit) { + return undefined; + } + const initSlice = Cell.fromBase64(stateInit).asSlice(); + return { + code: initSlice.loadRef(), + data: initSlice.loadRef(), + }; + }; + + private getJettonWallet = async (ownerAddress: string, contractAddress: string) => { + await this.readyPromise + const jettonMaster = this.client!.open(JettonMaster.create(Address.parse(contractAddress))); + const jettonWalletAddress = await jettonMaster.getWalletAddress(Address.parse(ownerAddress)) + const jettonWallet = this.client!.open(JettonWallet.create(jettonWalletAddress)) + return jettonWallet + } + + private createTonConnectTransfer = async (seqno: number, payload: TonConnectTransactionPayload) => { + await this.readyPromise + const transfer = this.wallet!.createTransfer({ + secretKey: this.keyPair!.secretKey, + seqno, + sendMode: SendMode.PAY_GAS_SEPARATELY + SendMode.IGNORE_ERRORS, + messages: payload.messages.map((item) => { + return internal({ + to: item.address, + value: toNano(fromNano(item.amount)), + bounce: this.getAddressBounceable(item.address), + init: this.toStateInit(item.stateInit), + body: item.payload ? Cell.fromBase64(item.payload) : undefined, + }); + }), + }); + return transfer; + }; +} diff --git a/packages/coin-ton/src/index.ts b/packages/coin-ton/src/index.ts new file mode 100644 index 00000000..b09c220d --- /dev/null +++ b/packages/coin-ton/src/index.ts @@ -0,0 +1,2 @@ +export * from './chain-wallet' +export * from './ton-connect' diff --git a/packages/coin-ton/src/ton-connect/index.ts b/packages/coin-ton/src/ton-connect/index.ts new file mode 100644 index 00000000..c970111f --- /dev/null +++ b/packages/coin-ton/src/ton-connect/index.ts @@ -0,0 +1 @@ +export type * from './types' diff --git a/packages/coin-ton/src/ton-connect/types.ts b/packages/coin-ton/src/ton-connect/types.ts new file mode 100644 index 00000000..d8cda439 --- /dev/null +++ b/packages/coin-ton/src/ton-connect/types.ts @@ -0,0 +1,46 @@ +import { DeviceInfo, ConnectEvent, AppRequest, WalletResponse, WalletEvent, ConnectRequest, CHAIN } from "@tonconnect/protocol"; + +export interface WalletInfo { + name: string; + image: string; + tondns?: string; + about_url: string; +} + +export type TonConnectCallback = (event: WalletEvent) => void; + +export interface TonConnectBridge { + deviceInfo: DeviceInfo; // see Requests/Responses spec + walletInfo?: WalletInfo; + protocolVersion: number; // max supported Ton Connect version (e.g. 2) + isWalletBrowser: boolean; // if the page is opened into wallet's browser + connect(protocolVersion: number, message: ConnectRequest): Promise; + restoreConnection(): Promise; + send(message: AppRequest<'sendTransaction' | 'signData' | 'disconnect'>): Promise>; + listen(callback: (event: WalletEvent) => void): () => void; +} + +export interface TonConnectTransactionPayloadMessage { + address: string // (string): message destination in user-friendly format + amount: string // (decimal string): number of nanocoins to send. + payload?: string // (string base64, optional): raw one-cell BoC encoded in Base64. + stateInit?: string // (string base64, optional) +} + +export interface TonConnectTransactionPayload { + valid_until?: number // (integer, optional): unix timestamp. after th moment transaction will be invalid. + network?: CHAIN // (NETWORK, optional): The network (mainnet or testnet) where DApp intends to send the transaction. If not set, the transaction is sent to the network currently set in the wallet, but this is not safe and DApp should always strive to set the network. If the network parameter is set, but the wallet has a different network set, the wallet should show an alert and DO NOT ALLOW TO SEND this transaction. + from?: string // (string in : format, optional) - The sender address from which DApp intends to send the transaction. If not set, wallet allows user to select the sender's address at the moment of transaction approval. If from parameter is set, the wallet should DO NOT ALLOW user to select the sender's address; If sending from the specified address is impossible, the wallet should show an alert and DO NOT ALLOW TO SEND this transaction. + messages: TonConnectTransactionPayloadMessage[] // (array of messages): 1-4 outgoing messages from the wallet contract to other accounts. All messages are sent out in order, however the wallet cannot guarantee that messages will be delivered and executed in same order. +} + +export interface TonConnectSignDataPayload { + schema_crc: number // (integer): indicates the layout of payload cell that in turn defines domain separation. + cell: string // (string, base64 encoded Cell): contains arbitrary data per its TL-B definition. + publicKey?: string // (HEX string without 0x, optional): The public key of key pair from which DApp intends to sign the data. If not set, the wallet is not limited in what keypair to sign. If publicKey parameter is set, the wallet SHOULD to sign by keypair corresponding this public key; If sign by this specified keypair is impossible, the wallet should show an alert and DO NOT ALLOW TO SIGN this data. +} + +export interface TonConnectSignDataResult { + signature: string; // base64 encoded signature + timestamp: string; // UNIX timestamp in seconds (UTC) at the moment on creating the signature. +} diff --git a/packages/coin-ton/src/vite-env.d.ts b/packages/coin-ton/src/vite-env.d.ts new file mode 100644 index 00000000..11f02fe2 --- /dev/null +++ b/packages/coin-ton/src/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/packages/coin-ton/tsconfig.json b/packages/coin-ton/tsconfig.json new file mode 100644 index 00000000..f48fcfc8 --- /dev/null +++ b/packages/coin-ton/tsconfig.json @@ -0,0 +1,12 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "baseUrl": ".", + "paths": { + "src/*": ["src/*"] + }, + "experimentalDecorators": true, + }, + "include": ["src"], + "exclude": ["**/node_modules"] +} diff --git a/packages/coin-ton/vite.config.ts b/packages/coin-ton/vite.config.ts new file mode 100644 index 00000000..0afab19b --- /dev/null +++ b/packages/coin-ton/vite.config.ts @@ -0,0 +1,38 @@ +import { defineConfig } from 'vite'; +import { resolve } from 'path'; +import typescript from '@rollup/plugin-typescript'; + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [], + resolve: { + alias: { + src: resolve(__dirname, 'src') + } + }, + build: { + lib: { + // Could also be a dictionary or array of multiple entry points + entry: resolve(__dirname, 'src/index.ts'), + name: 'CoinTon', + // the proper extensions will be added + fileName: 'coin-ton' + }, + commonjsOptions: { + transformMixedEsModules: true, + include: [/node_modules/] + }, + rollupOptions: { + plugins: [ + typescript({ + target: 'es2020', + rootDir: resolve(__dirname, 'src'), + declaration: true, + declarationDir: resolve(__dirname, 'dist'), + exclude: [resolve(__dirname, 'node_modules/**'), resolve(__dirname, 'test/**')], + allowSyntheticDefaultImports: true + }) + ] + } + } +}); diff --git a/packages/coin-tron/.gitignore b/packages/coin-tron/.gitignore new file mode 100644 index 00000000..a547bf36 --- /dev/null +++ b/packages/coin-tron/.gitignore @@ -0,0 +1,24 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +dist +dist-ssr +*.local + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +.DS_Store +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? diff --git a/packages/coin-tron/.prettierignore b/packages/coin-tron/.prettierignore new file mode 100644 index 00000000..bfe3b8d3 --- /dev/null +++ b/packages/coin-tron/.prettierignore @@ -0,0 +1 @@ +tsconfig.json \ No newline at end of file diff --git a/packages/coin-tron/package.json b/packages/coin-tron/package.json new file mode 100644 index 00000000..ba35f615 --- /dev/null +++ b/packages/coin-tron/package.json @@ -0,0 +1,46 @@ +{ + "name": "@delandlabs/coin-tron", + "private": false, + "version": "0.0.0", + "type": "module", + "files": [ + "dist" + ], + "main": "./dist/coin-tron.umd.cjs", + "module": "./dist/coin-tron.js", + "types": "dist/index.d.ts", + "exports": { + ".": { + "import": { + "types": "./dist/index.d.ts", + "default": "./dist/coin-tron.js" + }, + "require": { + "types": "./dist/index.d.ts", + "default": "./dist/coin-tron.umd.cjs" + } + } + }, + "scripts": { + "dev": "vite", + "test": "vitest", + "build": "vite build", + "lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0", + "format": "prettier --write ." + }, + "dependencies": { + "@delandlabs/coin-base": "*" + }, + "devDependencies": { + "@eslint/js": "^9.16.0", + "@rollup/plugin-typescript": "^12.1.1", + "@typescript-eslint/eslint-plugin": "^8.16.0", + "@typescript-eslint/parser": "^8.16.0", + "eslint": "^9.16.0", + "globals": "^15.12.0", + "typescript": "~5.6.2", + "typescript-eslint": "^8.16.0", + "vite": "^6.0.1", + "vitest": "^2.1.6" + } +} diff --git a/packages/coin-tron/src/chain-wallet/chain.ts b/packages/coin-tron/src/chain-wallet/chain.ts new file mode 100644 index 00000000..906cea40 --- /dev/null +++ b/packages/coin-tron/src/chain-wallet/chain.ts @@ -0,0 +1,86 @@ +import { ChainInfo, ChainId, Chain, ChainNetwork, Ecosystem, WalletSignatureSchema } from "@delandlabs/coin-base"; + +export const Tron: ChainInfo = { + chainId: new ChainId(Chain.Tron, ChainNetwork.TronMainNet), + name: 'Tron', + fullName: 'Tron Mainnet', + icon: '/chain-icons/Tron.svg', + nativeAssetSymbol: 'TRX', + nativeAssetDecimals: 6, + isMainnet: true, + isNativeGas: true, + ecosystem: Ecosystem.Tron, + supportedSignaturesSchemas: [WalletSignatureSchema.TronEcdsa], + explorer: 'https://tronscan.org', + rpcUrls: ['https://rpc.trongrid.io'], + caseSensitiveAddress: true, + getTxLink: (txId: string) => { + if (typeof txId !== 'string') { + return '' + } + const hash = txId.startsWith('0x') ? txId.slice(2) : txId; + return `https://tronscan.org/#/transaction/${hash}` + }, + getAddressLink: (address: string) => { + if (typeof address !== 'string') { + return '' + } + return `https://tronscan.org/#/address/${address}` + }, +}; +export const TronShasta: ChainInfo = { + chainId: new ChainId(Chain.Tron, ChainNetwork.TronShastaTestNet), + name: 'TronShasta', + fullName: 'Tron Shasta Testnet', + icon: '/chain-icons/Tron.svg', + nativeAssetSymbol: 'TRX', + nativeAssetDecimals: 6, + isMainnet: false, + isNativeGas: true, + ecosystem: Ecosystem.Tron, + supportedSignaturesSchemas: [WalletSignatureSchema.TronEcdsa], + explorer: 'https://shasta.tronscan.org', + rpcUrls: ['https://api.shasta.trongrid.io'], + caseSensitiveAddress: true, + getTxLink: (txId: string) => { + if (typeof txId !== 'string') { + return '' + } + const hash = txId.startsWith('0x') ? txId.slice(2) : txId; + return `https://shasta.tronscan.org/#/transaction/${hash}` + }, + getAddressLink: (address: string) => { + if (typeof address !== 'string') { + return '' + } + return `https://shasta.tronscan.org/#/address/${address}` + }, +}; +export const TronNile: ChainInfo = { + chainId: new ChainId(Chain.Tron, ChainNetwork.TronNileTestNet), + name: 'TronNile', + fullName: 'Tron Nile Testnet', + icon: '/chain-icons/Tron.svg', + nativeAssetSymbol: 'TRX', + nativeAssetDecimals: 6, + isMainnet: false, + isNativeGas: true, + ecosystem: Ecosystem.Tron, + supportedSignaturesSchemas: [WalletSignatureSchema.TronEcdsa], + explorer: 'https://nile.tronscan.org', + rpcUrls: ['https://api.nileex.io'], + caseSensitiveAddress: true, + getTxLink: (txId: string) => { + if (typeof txId !== 'string') { + return '' + } + const hash = txId.startsWith('0x') ? txId.slice(2) : txId; + return `https://nile.tronscan.org/#/transaction/${hash}` + }, + getAddressLink: (address: string) => { + if (typeof address !== 'string') { + return '' + } + return `https://nile.tronscan.org/#/address/${address}` + }, +} diff --git a/packages/coin-tron/src/chain-wallet/index.ts b/packages/coin-tron/src/chain-wallet/index.ts new file mode 100644 index 00000000..10dab0e7 --- /dev/null +++ b/packages/coin-tron/src/chain-wallet/index.ts @@ -0,0 +1,2 @@ +export * from './chain' +export * from './wallet' diff --git a/packages/coin-tron/src/chain-wallet/wallet.ts b/packages/coin-tron/src/chain-wallet/wallet.ts new file mode 100644 index 00000000..e69de29b diff --git a/packages/coin-tron/src/index.ts b/packages/coin-tron/src/index.ts new file mode 100644 index 00000000..02d3efed --- /dev/null +++ b/packages/coin-tron/src/index.ts @@ -0,0 +1 @@ +export * from './chain-wallet' diff --git a/packages/coin-tron/src/vite-env.d.ts b/packages/coin-tron/src/vite-env.d.ts new file mode 100644 index 00000000..11f02fe2 --- /dev/null +++ b/packages/coin-tron/src/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/packages/coin-tron/tsconfig.json b/packages/coin-tron/tsconfig.json new file mode 100644 index 00000000..f48fcfc8 --- /dev/null +++ b/packages/coin-tron/tsconfig.json @@ -0,0 +1,12 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "baseUrl": ".", + "paths": { + "src/*": ["src/*"] + }, + "experimentalDecorators": true, + }, + "include": ["src"], + "exclude": ["**/node_modules"] +} diff --git a/packages/coin-tron/vite.config.ts b/packages/coin-tron/vite.config.ts new file mode 100644 index 00000000..91b643a7 --- /dev/null +++ b/packages/coin-tron/vite.config.ts @@ -0,0 +1,38 @@ +import { defineConfig } from 'vite'; +import { resolve } from 'path'; +import typescript from '@rollup/plugin-typescript'; + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [], + resolve: { + alias: { + src: resolve(__dirname, 'src') + } + }, + build: { + lib: { + // Could also be a dictionary or array of multiple entry points + entry: resolve(__dirname, 'src/index.ts'), + name: 'CoinSolana', + // the proper extensions will be added + fileName: 'coin-tron' + }, + commonjsOptions: { + transformMixedEsModules: true, + include: [/node_modules/] + }, + rollupOptions: { + plugins: [ + typescript({ + target: 'es2020', + rootDir: resolve(__dirname, 'src'), + declaration: true, + declarationDir: resolve(__dirname, 'dist'), + exclude: [resolve(__dirname, 'node_modules/**'), resolve(__dirname, 'test/**')], + allowSyntheticDefaultImports: true + }) + ] + } + } +}); diff --git a/packages/crypto-lib/package.json b/packages/crypto-lib/package.json index ef2bc8b3..1f4ca3a0 100644 --- a/packages/crypto-lib/package.json +++ b/packages/crypto-lib/package.json @@ -16,11 +16,11 @@ ], "devDependencies": { "@types/bn.js": "^4.11.6", - "@types/create-hash": "1.2.6", - "@types/create-hmac": "1.1.3", + "@types/create-hash": "1.2.2", + "@types/create-hmac": "1.1.0", "@types/jest": "^27.5.1", "@types/node": "^12.20.52", - "@types/randombytes": "2.0.3", + "@types/randombytes": "2.0.0", "jest": "^27.5.1", "npm-run-all": "^4.1.5", "prettier": "2.6.2", @@ -32,7 +32,7 @@ "dependencies": { "@noble/ed25519": "^1.7.3", "@noble/hashes": "1.0.0", - "@noble/secp256k1": "^2.0.0", + "@noble/secp256k1": "^1.7.1", "@scure/base": "1.0.0", "asmcrypto.js": "^2.3.2", "bigint-conversion": "^2.3.0", diff --git a/packages/sdk/README.md b/packages/sdk/README.md index 44348707..75564a81 100644 --- a/packages/sdk/README.md +++ b/packages/sdk/README.md @@ -28,7 +28,7 @@ It supports a variety of popular third-party login methods which links user's We # Integration ## Install SDK ```bash -yarn add @delandlabs/hibit-id-sdk +yarn add @delandlabs/hibit-id-wallet-sdk ``` ## Usage ```js @@ -37,9 +37,9 @@ import { HibitIdChainId, WalletAccount, HibitIdAssetType, -} from "@delandlabs/hibit-id-sdk" +} from "@delandlabs/hibit-id-wallet-sdk" // remember to import styles for the wallet -import '@delandlabs/hibit-id-sdk/dist/style.css'; +import '@delandlabs/hibit-id-wallet-sdk/dist/style.css'; // init hibitid wallet const hibitId = new HibitIdWallet({ diff --git a/packages/sdk/src/lib/index.ts b/packages/sdk/src/lib/index.ts index e867dcad..71398755 100644 --- a/packages/sdk/src/lib/index.ts +++ b/packages/sdk/src/lib/index.ts @@ -20,6 +20,9 @@ export type { GetBalanceResponse, TransferRequest, TransferResponse, + TonConnectGetStateInitResponse, + TonConnectSignDataRequest, + TonConnectSignDataResponse, TonConnectTransferRequest, TonConnectTransferResponse, SwitchChainRequest, diff --git a/turbo.json b/turbo.json index e100fa70..af13c457 100644 --- a/turbo.json +++ b/turbo.json @@ -8,18 +8,68 @@ "outputs": ["dist/**"] }, + "@delandlabs/coin-base#build": { + "outputs": ["dist/**"] + }, + + "@delandlabs/coin-ethereum#build": { + "env": ["VITE_*"], + "dependsOn": [ + "@delandlabs/coin-base#build" + ], + "outputs": ["dist/**"] + }, + + "@delandlabs/coin-ton#build": { + "env": ["VITE_*"], + "dependsOn": [ + "@delandlabs/coin-base#build" + ], + "outputs": ["dist/**"] + }, + + "@delandlabs/coin-dfinity#build": { + "env": ["VITE_*"], + "dependsOn": [ + "@delandlabs/coin-base#build" + ], + "outputs": ["dist/**"] + }, + "@delandlabs/coin-kaspa#build": { "env": ["VITE_*"], - "dependsOn": ["@delandlabs/crypto-lib#build:esm"], + "dependsOn": [ + "@delandlabs/coin-base#build", + "@delandlabs/crypto-lib#build:esm" + ], "outputs": ["dist/**"] }, "@delandlabs/coin-kaspa#test": { "env": ["VITE_*"], - "dependsOn": ["@delandlabs/crypto-lib#build:common"], + "dependsOn": [ + "@delandlabs/coin-base#build", + "@delandlabs/crypto-lib#build:common" + ], "outputs": ["dist/**"], "persistent": true }, + "@delandlabs/coin-solana#build": { + "env": ["VITE_*"], + "dependsOn": [ + "@delandlabs/coin-base#build" + ], + "outputs": ["dist/**"] + }, + + "@delandlabs/coin-tron#build": { + "env": ["VITE_*"], + "dependsOn": [ + "@delandlabs/coin-base#build" + ], + "outputs": ["dist/**"] + }, + "@delandlabs/hibit-id-wallet-sdk#build": { "env": ["VITE_*"], "outputs": ["dist/**"] diff --git a/yarn.lock b/yarn.lock index d4ea9644..5c5dbd2c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -255,6 +255,13 @@ dependencies: "@babel/helper-plugin-utils" "^7.25.9" +"@babel/runtime@^7.25.0": + version "7.26.0" + resolved "https://registry.npmmirror.com/@babel/runtime/-/runtime-7.26.0.tgz#8600c2f595f277c60815256418b85356a65173c1" + integrity sha512-FDSOghenHTiToteC/QRlv2q3DhPZ/oOXTBoirfWNx1Cx3TMVcGWQtMMmQcSvb/JjpNeGzx8Pq/b4fKEJuWm1sw== + dependencies: + regenerator-runtime "^0.14.0" + "@babel/template@^7.25.9", "@babel/template@^7.3.3": version "7.25.9" resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.25.9.tgz#ecb62d81a8a6f5dc5fe8abfc3901fc52ddf15016" @@ -302,6 +309,89 @@ dependencies: "@jridgewell/trace-mapping" "0.3.9" +"@dfinity/agent@^0.19.2": + version "0.19.3" + resolved "https://registry.npmmirror.com/@dfinity/agent/-/agent-0.19.3.tgz#aa3f9c0f67d8e8f81714650ebb2a38e1b691021b" + integrity sha512-q410aNLoOA1ZkwdAMgSo6t++pjISn9TfSybRXhPRI5Ume7eG6+6qYr/rlvcXy7Nb2+Ar7LTsHNn34IULfjni7w== + dependencies: + "@noble/hashes" "^1.3.1" + base64-arraybuffer "^0.2.0" + borc "^2.1.1" + simple-cbor "^0.4.1" + +"@dfinity/agent@^2.1.1", "@dfinity/agent@^2.2.0": + version "2.2.0" + resolved "https://registry.npmmirror.com/@dfinity/agent/-/agent-2.2.0.tgz#3cb774091d166695eb4f97610dc17a47d7c2e48d" + integrity sha512-B0qpHf5vfnVNG3JZARC3Q9Cs2zG51/3LuTpCF4uVZ+4AgeRYHl4Erk/jmczdHNbSLIz1pe+F9seAYICovAnRIQ== + dependencies: + "@noble/curves" "^1.4.0" + "@noble/hashes" "^1.3.1" + base64-arraybuffer "^0.2.0" + borc "^2.1.1" + buffer "^6.0.3" + simple-cbor "^0.4.1" + +"@dfinity/candid@^0.19.2": + version "0.19.3" + resolved "https://registry.npmmirror.com/@dfinity/candid/-/candid-0.19.3.tgz#edc3491572d293824b821ce3a4fc50f5b4714f4d" + integrity sha512-yXfbLSWTeRd4G0bLLxYoDqpXH3Jim0P+1PPZOoktXNC1X1hB+ea3yrZebX75t4GVoQK7123F7mxWHiPjuV2tQQ== + +"@dfinity/candid@^2.1.1": + version "2.2.0" + resolved "https://registry.npmmirror.com/@dfinity/candid/-/candid-2.2.0.tgz#baf69d32f4f99296ee9d43c40930a24f13559147" + integrity sha512-6r21ow4kI/JaS6PocMVSHP49UDRG32EHrmFK9Uvg11yXulyTiR+PLGjabajvJjwmPQhjXiF8VzBIFY7aHOHiqQ== + +"@dfinity/identity-secp256k1@^2.1.1": + version "2.2.0" + resolved "https://registry.npmmirror.com/@dfinity/identity-secp256k1/-/identity-secp256k1-2.2.0.tgz#1b637bc5687f70bf35d0bfb1eaefa71fa312ba05" + integrity sha512-e4dWqwycZlOzGp4xc5NTJmKvjJvdG2FjnxMA41ZuccHQ/fuHPmhSuAtRJ6BO36bAyY3lN6QPtyE3Wnw3NkbiSg== + dependencies: + "@dfinity/agent" "^2.2.0" + "@noble/curves" "^1.4.0" + "@noble/hashes" "^1.3.1" + "@scure/bip32" "^1.4.0" + "@scure/bip39" "^1.3.0" + asn1js "^3.0.5" + bs58check "^3.0.1" + +"@dfinity/identity@^0.19.2": + version "0.19.3" + resolved "https://registry.npmmirror.com/@dfinity/identity/-/identity-0.19.3.tgz#caec4a38b4a7d4567e662a7eb5bf2a9ae6466bdf" + integrity sha512-6XHrkNQ8tVN6+MERyXPy+avGHTd2zoX3l47bu6gSwreDdOZQnAnXpHVzLcXhnUptkBVetcC70YQEKCmqtuLriA== + dependencies: + "@noble/hashes" "^1.3.1" + borc "^2.1.1" + tweetnacl "^1.0.1" + +"@dfinity/ledger-icp@^2.5.0": + version "2.6.4" + resolved "https://registry.npmmirror.com/@dfinity/ledger-icp/-/ledger-icp-2.6.4.tgz#5c20b9d848ce6650455a9484ea9665f6733bec24" + integrity sha512-RbvDiMcMRCok4c3s4xoHg8nwatsFFZgQcZkV/TTn7MpfnLgmMWtTGx97astv0fpj5cCLOl/NXbJhJd+Z+g8eEg== + +"@dfinity/ledger-icrc@^2.5.0": + version "2.6.4" + resolved "https://registry.npmmirror.com/@dfinity/ledger-icrc/-/ledger-icrc-2.6.4.tgz#37d526725484559888c0060c34537236f24c41bb" + integrity sha512-Q7B/D6NhmWQW4qFWZVaV8B6efuRto7hDa0GmT1hxeeUPcyXt42AtfNgyqByDu82Wsank90AW4hgBS0UhKGEB9Q== + +"@dfinity/principal@^0.19.2": + version "0.19.3" + resolved "https://registry.npmmirror.com/@dfinity/principal/-/principal-0.19.3.tgz#428cfca3d2d2de9e1433b3b33498fd595fb441d8" + integrity sha512-+nixVvdGt7ECxRvLXDXsvU9q9sSPssBtDQ4bXa149SK6gcYcmZ6lfWIi3DJNqj3tGROxILVBsguel9tECappsA== + dependencies: + "@noble/hashes" "^1.3.1" + +"@dfinity/principal@^2.1.1": + version "2.2.0" + resolved "https://registry.npmmirror.com/@dfinity/principal/-/principal-2.2.0.tgz#36bd46e9e4d9d96eee8288b0c68762299e081dcf" + integrity sha512-8Yxb/6B4BWvV64HJ7X8sbDjoBaEamAQgOZ0MK0I44lZiRHomAYeUJMrw3yBg9jI1T62lijLcl401FAXBOzciiQ== + dependencies: + "@noble/hashes" "^1.3.1" + +"@dfinity/utils@^2.5.0": + version "2.7.1" + resolved "https://registry.npmmirror.com/@dfinity/utils/-/utils-2.7.1.tgz#fdfc4e5e79c9240bd7621fe6f7282bf8212bc55f" + integrity sha512-61DFOBmRomKLQUqBYuiUaqE+bFeGs31bjCQjOlWMQghJAEC7gxOlapasZFGBMVGEYITGy48hFczWaVGtYRfTjw== + "@esbuild/aix-ppc64@0.21.5": version "0.21.5" resolved "https://registry.yarnpkg.com/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz#c7184a326533fcdf1b8ee0733e21c713b975575f" @@ -865,6 +955,66 @@ resolved "https://registry.yarnpkg.com/@juanelas/base64/-/base64-1.1.5.tgz#d43b3c78e32e609d9b17a15e4f1b6342c9ca1238" integrity sha512-mjAF27LzwfYobdwqnxZgeucbKT5wRRNvILg3h5OvCWK+3F7mw/A1tnjHnNiTYtLmTvT/bM1jA5AX7eQawDGs1w== +"@ledgerhq/devices@^5.48.0", "@ledgerhq/devices@^5.51.1": + version "5.51.1" + resolved "https://registry.npmmirror.com/@ledgerhq/devices/-/devices-5.51.1.tgz#d741a4a5d8f17c2f9d282fd27147e6fe1999edb7" + integrity sha512-4w+P0VkbjzEXC7kv8T1GJ/9AVaP9I6uasMZ/JcdwZBS3qwvKo5A5z9uGhP5c7TvItzcmPb44b5Mw2kT+WjUuAA== + dependencies: + "@ledgerhq/errors" "^5.50.0" + "@ledgerhq/logs" "^5.50.0" + rxjs "6" + semver "^7.3.5" + +"@ledgerhq/errors@^5.48.0", "@ledgerhq/errors@^5.50.0": + version "5.50.0" + resolved "https://registry.npmmirror.com/@ledgerhq/errors/-/errors-5.50.0.tgz#e3a6834cb8c19346efca214c1af84ed28e69dad9" + integrity sha512-gu6aJ/BHuRlpU7kgVpy2vcYk6atjB4iauP2ymF7Gk0ez0Y/6VSMVSJvubeEQN+IV60+OBK0JgeIZG7OiHaw8ow== + +"@ledgerhq/hw-transport-web-ble@5.48.0": + version "5.48.0" + resolved "https://registry.npmmirror.com/@ledgerhq/hw-transport-web-ble/-/hw-transport-web-ble-5.48.0.tgz#41b29293c263d8ed4200037eb6da4db3bd4268a6" + integrity sha512-ezgssFvxc4/UbfwIxwg9jEn0/yiND8TW6bDkaE3kAqKCa8ZYYgFtms8iRqjTOJlqcbSYkudbNhP74jtY0NxfdA== + dependencies: + "@ledgerhq/devices" "^5.48.0" + "@ledgerhq/errors" "^5.48.0" + "@ledgerhq/hw-transport" "^5.48.0" + "@ledgerhq/logs" "^5.48.0" + rxjs "^6.6.7" + +"@ledgerhq/hw-transport-webhid@5.48.0": + version "5.48.0" + resolved "https://registry.npmmirror.com/@ledgerhq/hw-transport-webhid/-/hw-transport-webhid-5.48.0.tgz#aab2cffac3d5c97b04f093e2a0cbfe311dfdeab4" + integrity sha512-g6TYxgPX3MqP3jQ4SJaJjlM+2SwUSk4Si/9MeKLwz5ySbiD3bSTh/Gbzv8VBCaHPO4fILujc5vW/xejJuMzR8w== + dependencies: + "@ledgerhq/devices" "^5.48.0" + "@ledgerhq/errors" "^5.48.0" + "@ledgerhq/hw-transport" "^5.48.0" + "@ledgerhq/logs" "^5.48.0" + +"@ledgerhq/hw-transport-webusb@5.48.0": + version "5.48.0" + resolved "https://registry.npmmirror.com/@ledgerhq/hw-transport-webusb/-/hw-transport-webusb-5.48.0.tgz#62e5bffffba853d4e06103f7c8e9b6c87ca0f994" + integrity sha512-tO+p11aRQx9q9ifmi/NCbCBKQ738lp+PROy1BWSzjCJcUEz1sKTLeRTLE2Xze25KebhuM2YR1NgkX5LN1z4upA== + dependencies: + "@ledgerhq/devices" "^5.48.0" + "@ledgerhq/errors" "^5.48.0" + "@ledgerhq/hw-transport" "^5.48.0" + "@ledgerhq/logs" "^5.48.0" + +"@ledgerhq/hw-transport@^5.48.0": + version "5.51.1" + resolved "https://registry.npmmirror.com/@ledgerhq/hw-transport/-/hw-transport-5.51.1.tgz#8dd14a8e58cbee4df0c29eaeef983a79f5f22578" + integrity sha512-6wDYdbWrw9VwHIcoDnqWBaDFyviyjZWv6H9vz9Vyhe4Qd7TIFmbTl/eWs6hZvtZBza9K8y7zD8ChHwRI4s9tSw== + dependencies: + "@ledgerhq/devices" "^5.51.1" + "@ledgerhq/errors" "^5.50.0" + events "^3.3.0" + +"@ledgerhq/logs@^5.48.0", "@ledgerhq/logs@^5.50.0": + version "5.50.0" + resolved "https://registry.npmmirror.com/@ledgerhq/logs/-/logs-5.50.0.tgz#29c6419e8379d496ab6d0426eadf3c4d100cd186" + integrity sha512-swKHYCOZUGyVt4ge0u8a7AwNcA//h4nx5wIi0sruGye1IJ5Cva0GyK9L2/WdX+kWVTKp92ZiEo1df31lrWGPgA== + "@mapbox/node-pre-gyp@^1.0.5": version "1.0.11" resolved "https://registry.npmmirror.com/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.11.tgz#417db42b7f5323d79e93b34a6d7a2a12c0df43fa" @@ -894,6 +1044,13 @@ dependencies: "@noble/hashes" "1.3.2" +"@noble/curves@^1.4.0", "@noble/curves@^1.4.2", "@noble/curves@~1.7.0": + version "1.7.0" + resolved "https://registry.npmmirror.com/@noble/curves/-/curves-1.7.0.tgz#0512360622439256df892f21d25b388f52505e45" + integrity sha512-UTMhXK9SeDhFJVrHeUJ5uZlI6ajXg10O6Ddocf9S6GjbSBVZsJo88HzKwXznNfGpMTRDyJkqMjNDPYgf0qFWnw== + dependencies: + "@noble/hashes" "1.6.0" + "@noble/ed25519@^1.7.3": version "1.7.3" resolved "https://registry.yarnpkg.com/@noble/ed25519/-/ed25519-1.7.3.tgz#57e1677bf6885354b466c38e2b620c62f45a7123" @@ -909,10 +1066,20 @@ resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.3.2.tgz#6f26dbc8fbc7205873ce3cee2f690eba0d421b39" integrity sha512-MVC8EAQp7MvEcm30KWENFjgR+Mkmf+D189XJTkFIlwohU5hcBbn1ZkKq7KVTi2Hme3PMGF390DaL52beVrIihQ== -"@noble/secp256k1@^2.0.0": - version "2.1.0" - resolved "https://registry.yarnpkg.com/@noble/secp256k1/-/secp256k1-2.1.0.tgz#71d829a0b8ce84aea137708f82273977eea84597" - integrity sha512-XLEQQNdablO0XZOIniFQimiXsZDNwaYgL96dZwC54Q30imSbAOFf3NKtepc+cXyuZf5Q1HCgbqgZ2UFFuHVcEw== +"@noble/hashes@1.6.0": + version "1.6.0" + resolved "https://registry.npmmirror.com/@noble/hashes/-/hashes-1.6.0.tgz#d4bfb516ad6e7b5111c216a5cc7075f4cf19e6c5" + integrity sha512-YUULf0Uk4/mAA89w+k3+yUYh6NrEvxZa5T6SY3wlMvE2chHkxFUUIDI8/XW1QSC357iA5pSnqt7XEhvFOqmDyQ== + +"@noble/hashes@^1.2.0", "@noble/hashes@^1.3.1", "@noble/hashes@^1.4.0", "@noble/hashes@~1.6.0": + version "1.6.1" + resolved "https://registry.npmmirror.com/@noble/hashes/-/hashes-1.6.1.tgz#df6e5943edcea504bac61395926d6fd67869a0d5" + integrity sha512-pq5D8h10hHBjyqX+cfBm0i8JUXJ0UhczFc4r74zbuT9XgewFo2E3J1cOaGtdZynILNmQ685YWGzGE1Zv6io50w== + +"@noble/secp256k1@^1.7.0", "@noble/secp256k1@^1.7.1": + version "1.7.1" + resolved "https://registry.yarnpkg.com/@noble/secp256k1/-/secp256k1-1.7.1.tgz#b251c70f824ce3ca7f8dc3df08d58f005cc0507c" + integrity sha512-hOUk6AyBFmqVrv7k5WAw/LpszxVbj9gGN4JRkIX52fdFAj1UA61KXmZDvqVEm+pOyec3+fIeZB02LYa/pWOArw== "@nodelib/fs.scandir@2.1.5": version "2.1.5" @@ -935,11 +1102,55 @@ "@nodelib/fs.scandir" "2.1.5" fastq "^1.6.0" +"@openproduct/web-sdk@^0.23.0": + version "0.23.0" + resolved "https://registry.npmmirror.com/@openproduct/web-sdk/-/web-sdk-0.23.0.tgz#bb9e6bfaaa88647236b352c90e84cfe08c096c7e" + integrity sha512-teC+NLZStzM7Vrmj2ZR1dzXVp2KxDbj6TStjSuzvPcrmR7xjSKAfu71IUFWZSzxFDrZwHx0J8elnx/JqJZSZzQ== + dependencies: + bn.js "4.11.6" + ethjs-unit "0.1.6" + jssha "^3.3.0" + tweetnacl "1.0.3" + +"@orbs-network/ton-access@^2.3.3": + version "2.3.3" + resolved "https://registry.npmmirror.com/@orbs-network/ton-access/-/ton-access-2.3.3.tgz#20292f83b52a75f451f185821180a7d9b829bcd3" + integrity sha512-b1miCPts7wBG9JKYgzXIRZQm/LMy5Uk1mNK8NzlcXHL3HRHJkkFbuYJGuj3IkWCiIicW3Ipp4sYnn3Fwo4oB0g== + dependencies: + isomorphic-fetch "^3.0.0" + "@passwordless-id/webauthn@^1.6.1": version "1.6.2" resolved "https://registry.yarnpkg.com/@passwordless-id/webauthn/-/webauthn-1.6.2.tgz#677e963280eac2a98eb3317b54c80f9f59d56d15" integrity sha512-52Cna/kaJ6iuYgTko+LuHCY5NUgoJTQ+iLWbvCHWiI0pT+zUeKz1+g22mWGlSi/JDrFGwZTKG/PL2YDaQGo0qQ== +"@peculiar/asn1-schema@^2.3.13", "@peculiar/asn1-schema@^2.3.8": + version "2.3.13" + resolved "https://registry.npmmirror.com/@peculiar/asn1-schema/-/asn1-schema-2.3.13.tgz#ec8509cdcbc0da3abe73fd7e690556b57a61b8f4" + integrity sha512-3Xq3a01WkHRZL8X04Zsfg//mGaA21xlL4tlVn4v2xGT0JStiztATRkMwa5b+f/HXmY2smsiLXYK46Gwgzvfg3g== + dependencies: + asn1js "^3.0.5" + pvtsutils "^1.3.5" + tslib "^2.6.2" + +"@peculiar/json-schema@^1.1.12": + version "1.1.12" + resolved "https://registry.npmmirror.com/@peculiar/json-schema/-/json-schema-1.1.12.tgz#fe61e85259e3b5ba5ad566cb62ca75b3d3cd5339" + integrity sha512-coUfuoMeIB7B8/NMekxaDzLhaYmp0HZNPEjYRm9goRou8UZIC3z21s0sL9AWoCw4EG876QyO3kYrc61WNF9B/w== + dependencies: + tslib "^2.0.0" + +"@peculiar/webcrypto@^1.0.22": + version "1.5.0" + resolved "https://registry.npmmirror.com/@peculiar/webcrypto/-/webcrypto-1.5.0.tgz#9e57174c02c1291051c553600347e12b81469e10" + integrity sha512-BRs5XUAwiyCDQMsVA9IDvDa7UBR9gAvPHgugOeGng3YN6vJ9JYonyDc0lNczErgtCWtucjR5N7VtaonboD/ezg== + dependencies: + "@peculiar/asn1-schema" "^2.3.8" + "@peculiar/json-schema" "^1.1.12" + pvtsutils "^1.3.5" + tslib "^2.6.2" + webcrypto-core "^1.8.0" + "@pkgjs/parseargs@^0.11.0": version "0.11.0" resolved "https://registry.yarnpkg.com/@pkgjs/parseargs/-/parseargs-0.11.0.tgz#a77ea742fab25775145434eb1d2328cf5013ac33" @@ -1127,6 +1338,28 @@ resolved "https://registry.yarnpkg.com/@scure/base/-/base-1.0.0.tgz#109fb595021de285f05a7db6806f2f48296fcee7" integrity sha512-gIVaYhUsy+9s58m/ETjSJVKHhKTBMmcRb9cEV5/5dwvfDlfORjKrFsDeDHWRrm6RjcPvCLZFwGJjAjLj1gg4HA== +"@scure/base@~1.2.1": + version "1.2.1" + resolved "https://registry.npmmirror.com/@scure/base/-/base-1.2.1.tgz#dd0b2a533063ca612c17aa9ad26424a2ff5aa865" + integrity sha512-DGmGtC8Tt63J5GfHgfl5CuAXh96VF/LD8K9Hr/Gv0J2lAoRGlPOMpqMpMbCTOoOJMZCk2Xt+DskdDyn6dEFdzQ== + +"@scure/bip32@^1.4.0": + version "1.6.0" + resolved "https://registry.npmmirror.com/@scure/bip32/-/bip32-1.6.0.tgz#6dbc6b4af7c9101b351f41231a879d8da47e0891" + integrity sha512-82q1QfklrUUdXJzjuRU7iG7D7XiFx5PHYVS0+oeNKhyDLT7WPqs6pBcM2W5ZdwOwKCwoE1Vy1se+DHjcXwCYnA== + dependencies: + "@noble/curves" "~1.7.0" + "@noble/hashes" "~1.6.0" + "@scure/base" "~1.2.1" + +"@scure/bip39@^1.3.0": + version "1.5.0" + resolved "https://registry.npmmirror.com/@scure/bip39/-/bip39-1.5.0.tgz#c8f9533dbd787641b047984356531d84485f19be" + integrity sha512-Dop+ASYhnrwm9+HA/HwXg7j2ZqM6yk2fyLWb5znexjctFY3+E+eU8cIWI0Pql0Qx4hPZCijlGq4OL71g+Uz30A== + dependencies: + "@noble/hashes" "~1.6.0" + "@scure/base" "~1.2.1" + "@sinonjs/commons@^1.7.0": version "1.8.6" resolved "https://registry.yarnpkg.com/@sinonjs/commons/-/commons-1.8.6.tgz#80c516a4dc264c2a69115e7578d62581ff455ed9" @@ -1141,6 +1374,34 @@ dependencies: "@sinonjs/commons" "^1.7.0" +"@solana/buffer-layout@^4.0.1": + version "4.0.1" + resolved "https://registry.npmmirror.com/@solana/buffer-layout/-/buffer-layout-4.0.1.tgz#b996235eaec15b1e0b5092a8ed6028df77fa6c15" + integrity sha512-E1ImOIAD1tBZFRdjeM4/pzTiTApC0AOBGwyAMS4fwIodCWArzJ3DWdoh8cKxeFM2fElkxBh2Aqts1BPC373rHA== + dependencies: + buffer "~6.0.3" + +"@solana/web3.js@^1.94.0": + version "1.98.0" + resolved "https://registry.npmmirror.com/@solana/web3.js/-/web3.js-1.98.0.tgz#21ecfe8198c10831df6f0cfde7f68370d0405917" + integrity sha512-nz3Q5OeyGFpFCR+erX2f6JPt3sKhzhYcSycBCSPkWjzSVDh/Rr1FqTVMRe58FKO16/ivTUcuJjeS5MyBvpkbzA== + dependencies: + "@babel/runtime" "^7.25.0" + "@noble/curves" "^1.4.2" + "@noble/hashes" "^1.4.0" + "@solana/buffer-layout" "^4.0.1" + agentkeepalive "^4.5.0" + bigint-buffer "^1.1.5" + bn.js "^5.2.1" + borsh "^0.7.0" + bs58 "^4.0.1" + buffer "6.0.3" + fast-stable-stringify "^1.0.0" + jayson "^4.1.1" + node-fetch "^2.7.0" + rpc-websockets "^9.0.2" + superstruct "^2.0.2" + "@svgr/babel-plugin-add-jsx-attribute@8.0.0": version "8.0.0" resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-add-jsx-attribute/-/babel-plugin-add-jsx-attribute-8.0.0.tgz#4001f5d5dd87fa13303e36ee106e3ff3a7eb8b22" @@ -1298,6 +1559,13 @@ resolved "https://registry.yarnpkg.com/@swc/counter/-/counter-0.1.3.tgz#cc7463bd02949611c6329596fccd2b0ec782b0e9" integrity sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ== +"@swc/helpers@^0.5.11": + version "0.5.15" + resolved "https://registry.npmmirror.com/@swc/helpers/-/helpers-0.5.15.tgz#79efab344c5819ecf83a43f3f9f811fc84b516d7" + integrity sha512-JQ5TuMi45Owi4/BIMAJBoSQoOJu12oOk/gADqlcUL9JEdHB8vyjUSsxqeNXnmXHjYKMi2WcYtezGEEhqUI/E2g== + dependencies: + tslib "^2.8.0" + "@swc/types@^0.1.17": version "0.1.17" resolved "https://registry.yarnpkg.com/@swc/types/-/types-0.1.17.tgz#bd1d94e73497f27341bf141abdf4c85230d41e7c" @@ -1305,6 +1573,13 @@ dependencies: "@swc/counter" "^0.1.3" +"@ton/core@^0.56.3": + version "0.56.3" + resolved "https://registry.npmmirror.com/@ton/core/-/core-0.56.3.tgz#1162764573abb76032eba70f8497e5cb2ea532ee" + integrity sha512-HVkalfqw8zqLLPehtq0CNhu5KjVzc7IrbDwDHPjGoOSXmnqSobiWj8a5F+YuWnZnEbQKtrnMGNOOjVw4LG37rg== + dependencies: + symbol.inspect "1.0.1" + "@ton/core@^0.57.0": version "0.57.0" resolved "https://registry.yarnpkg.com/@ton/core/-/core-0.57.0.tgz#fdf2d32848a3d1135b890e9a5bd8295e958a4a81" @@ -1328,6 +1603,17 @@ jssha "3.2.0" tweetnacl "1.0.3" +"@ton/ton@^14.0.0": + version "14.0.0" + resolved "https://registry.npmmirror.com/@ton/ton/-/ton-14.0.0.tgz#a66fbbfb159200892557442039a0341cda71fc2d" + integrity sha512-xb2CY6U0AlHUKc7DV7xK/K4Gqn6YoR253yUrM2E7L5WegVFsDF0CQRUIfpYACCuj1oUywQc5J2oMolYNu/uGkA== + dependencies: + axios "^1.6.7" + dataloader "^2.0.0" + symbol.inspect "1.0.1" + teslabot "^1.3.0" + zod "^3.21.4" + "@ton/ton@^15.0.0": version "15.1.0" resolved "https://registry.yarnpkg.com/@ton/ton/-/ton-15.1.0.tgz#a760b1492dd3e5896238b7154f7377f4e51fa086" @@ -1412,22 +1698,29 @@ dependencies: "@types/node" "*" +"@types/connect@^3.4.33": + version "3.4.38" + resolved "https://registry.npmmirror.com/@types/connect/-/connect-3.4.38.tgz#5ba7f3bc4fbbdeaff8dded952e5ff2cc53f8d858" + integrity sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug== + dependencies: + "@types/node" "*" + "@types/cookie@^0.6.0": version "0.6.0" resolved "https://registry.npmmirror.com/@types/cookie/-/cookie-0.6.0.tgz#eac397f28bf1d6ae0ae081363eca2f425bedf0d5" integrity sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA== -"@types/create-hash@1.2.6": - version "1.2.6" - resolved "https://registry.yarnpkg.com/@types/create-hash/-/create-hash-1.2.6.tgz#ef9de147f4bf7d3fcfded4862726de949d8d44f4" - integrity sha512-/VIViZZAK3rAFvfGbWmcLaxwKfmU213W/XL2cr5VE0ac44jE5ky7+sHl54OJhd+bTz7sqi+Ev//8RU1F/S/ZJQ== +"@types/create-hash@1.2.2": + version "1.2.2" + resolved "https://registry.yarnpkg.com/@types/create-hash/-/create-hash-1.2.2.tgz#e87247083df8478f6b83655592bde0d709028235" + integrity sha512-Fg8/kfMJObbETFU/Tn+Y0jieYewryLrbKwLCEIwPyklZZVY2qB+64KFjhplGSw+cseZosfFXctXO+PyIYD8iZQ== dependencies: "@types/node" "*" -"@types/create-hmac@1.1.3": - version "1.1.3" - resolved "https://registry.yarnpkg.com/@types/create-hmac/-/create-hmac-1.1.3.tgz#fba2fe41fb98d37b76da2ca5a7158dc7408727dc" - integrity sha512-oDDSoBrAfdEPQuBpQp14y/ygUVU1IC6gq8Arm8IPP8TRC11AnLLYmpE3VvNUhPK/Ax3USGDjdE1Sc1LCIpf0NQ== +"@types/create-hmac@1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@types/create-hmac/-/create-hmac-1.1.0.tgz#d5bc34b65aeaf8f7bbd4a064172ab48318763b63" + integrity sha512-BNYNdzdhOZZQWCOpwvIll3FSvgo3e55Y2M6s/jOY6TuOCwqt3cLmQsK4tSmJ5fayDot8EG4k3+hcZagfww9JlQ== dependencies: "@types/node" "*" @@ -1494,7 +1787,7 @@ dependencies: undici-types "~6.19.2" -"@types/node@^12.20.52": +"@types/node@^12.12.54", "@types/node@^12.20.52": version "12.20.55" resolved "https://registry.yarnpkg.com/@types/node/-/node-12.20.55.tgz#c329cbd434c42164f846b909bd6f85b5537f6240" integrity sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ== @@ -1509,10 +1802,10 @@ resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.13.tgz#2af91918ee12d9d32914feb13f5326658461b451" integrity sha512-hCZTSvwbzWGvhqxp/RqVqwU999pBf2vp7hzIjiYOsl8wqOmUxkQ6ddw1cV3l8811+kdUFus/q4d1Y3E3SyEifA== -"@types/randombytes@2.0.3": - version "2.0.3" - resolved "https://registry.yarnpkg.com/@types/randombytes/-/randombytes-2.0.3.tgz#c83a107ef51ae7a8611a7b964f54b21cb782bbed" - integrity sha512-+NRgihTfuURllWCiIAhm1wsJqzsocnqXM77V/CalsdJIYSRGEHMnritxh+6EsBklshC+clo1KgnN14qgSGeQdw== +"@types/randombytes@2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@types/randombytes/-/randombytes-2.0.0.tgz#0087ff5e60ae68023b9bc4398b406fea7ad18304" + integrity sha512-bz8PhAVlwN72vqefzxa14DKNT8jK/mV66CSjwdVQM/k3Th3EPKfUtdMniwZgMedQTFuywAsfjnZsg+pEnltaMA== dependencies: "@types/node" "*" @@ -1536,6 +1829,25 @@ resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-2.0.3.tgz#6209321eb2c1712a7e7466422b8cb1fc0d9dd5d8" integrity sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw== +"@types/uuid@^8.3.4": + version "8.3.4" + resolved "https://registry.npmmirror.com/@types/uuid/-/uuid-8.3.4.tgz#bd86a43617df0594787d38b735f55c805becf1bc" + integrity sha512-c/I8ZRb51j+pYGAu5CrFMRxqZ2ke4y2grEBO5AUjgSkSk+qT2Ea+OdWElz/OiMf5MNpn2b17kuVBwZLQJXzihw== + +"@types/ws@^7.4.4": + version "7.4.7" + resolved "https://registry.npmmirror.com/@types/ws/-/ws-7.4.7.tgz#f7c390a36f7a0679aa69de2d501319f4f8d9b702" + integrity sha512-JQbbmxZTZehdc2iszGKs5oC3NFnjeay7mtAWrdt7qNtAVK0g19muApzAy4bm9byz79xa2ZnO/BOBC2R8RC5Lww== + dependencies: + "@types/node" "*" + +"@types/ws@^8.2.2": + version "8.5.13" + resolved "https://registry.npmmirror.com/@types/ws/-/ws-8.5.13.tgz#6414c280875e2691d0d1e080b05addbf5cb91e20" + integrity sha512-osM/gWBTPKgHV8XkTunnegTRIsvF6owmf5w+JtAfOw472dptdm0dlGv4xCt6GwQRcC2XVOvvRE/0bAoQcL2QkA== + dependencies: + "@types/node" "*" + "@types/yargs-parser@*": version "21.0.3" resolved "https://registry.yarnpkg.com/@types/yargs-parser/-/yargs-parser-21.0.3.tgz#815e30b786d2e8f0dcd85fd5bcf5e1a04d008f15" @@ -1629,6 +1941,21 @@ "@typescript-eslint/types" "8.16.0" eslint-visitor-keys "^4.2.0" +"@unimodules/core@*": + version "7.1.2" + resolved "https://registry.npmmirror.com/@unimodules/core/-/core-7.1.2.tgz#5181b99586476a5d87afd0958f26a04714c47fa1" + integrity sha512-lY+e2TAFuebD3vshHMIRqru3X4+k7Xkba4Wa7QsDBd+ex4c4N2dHAO61E2SrGD9+TRBD8w/o7mzK6ljbqRnbyg== + dependencies: + compare-versions "^3.4.0" + +"@unimodules/react-native-adapter@*": + version "6.3.9" + resolved "https://registry.npmmirror.com/@unimodules/react-native-adapter/-/react-native-adapter-6.3.9.tgz#2f4bef6b7532dce5bf9f236e69f96403d0243c30" + integrity sha512-i9/9Si4AQ8awls+YGAKkByFbeAsOPgUNeLoYeh2SQ3ddjxJ5ZJDtq/I74clDnpDcn8zS9pYlcDJ9fgVJa39Glw== + dependencies: + expo-modules-autolinking "^0.0.3" + invariant "^2.2.4" + "@vitejs/plugin-basic-ssl@^1.2.0": version "1.2.0" resolved "https://registry.npmmirror.com/@vitejs/plugin-basic-ssl/-/plugin-basic-ssl-1.2.0.tgz#9490fe15b8833351982fbe0963987f69f40f5019" @@ -1711,6 +2038,14 @@ loupe "^3.1.2" tinyrainbow "^1.2.0" +JSONStream@^1.3.5: + version "1.3.5" + resolved "https://registry.npmmirror.com/JSONStream/-/JSONStream-1.3.5.tgz#3208c1f08d3a4d99261ab64f92302bc15e111ca0" + integrity sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ== + dependencies: + jsonparse "^1.2.0" + through ">=2.2.7 <3" + abab@^2.0.3, abab@^2.0.5: version "2.0.6" resolved "https://registry.yarnpkg.com/abab/-/abab-2.0.6.tgz#41b80f2c871d19686216b82309231cfd3cb3d291" @@ -1773,6 +2108,13 @@ agent-base@6: dependencies: debug "4" +agentkeepalive@^4.5.0: + version "4.5.0" + resolved "https://registry.npmmirror.com/agentkeepalive/-/agentkeepalive-4.5.0.tgz#2673ad1389b3c418c5a20c5d7364f93ca04be923" + integrity sha512-5GG/5IbQQpC9FpkRGsSvZI5QYeSCzlJHdpBQntCsuTOxhKD8lqKhrleg2Yi7yvMIf82Ycmmqln9U8V9qwEiJew== + dependencies: + humanize-ms "^1.2.1" + ajv@^6.12.4: version "6.12.6" resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" @@ -1901,6 +2243,11 @@ arraybuffer.prototype.slice@^1.0.3: is-array-buffer "^3.0.4" is-shared-array-buffer "^1.0.2" +asmcrypto.js@^0.22.0: + version "0.22.0" + resolved "https://registry.npmmirror.com/asmcrypto.js/-/asmcrypto.js-0.22.0.tgz#38fc1440884d802c7bd37d1d23c2b26a5cd5d2d2" + integrity sha512-usgMoyXjMbx/ZPdzTSXExhMPur2FTdz/Vo5PVx2gIaBcdAAJNOFlsdgqveM8Cff7W0v+xrf9BwjOV26JSAF9qA== + asmcrypto.js@^2.3.2: version "2.3.2" resolved "https://registry.yarnpkg.com/asmcrypto.js/-/asmcrypto.js-2.3.2.tgz#b9f84bd0a1fb82f21f8c29cc284a707ad17bba2e" @@ -1915,6 +2262,15 @@ asn1.js@^4.10.1: inherits "^2.0.1" minimalistic-assert "^1.0.0" +asn1js@^3.0.5: + version "3.0.5" + resolved "https://registry.npmmirror.com/asn1js/-/asn1js-3.0.5.tgz#5ea36820443dbefb51cc7f88a2ebb5b462114f38" + integrity sha512-FVnvrKJwpt9LP2lAMl8qZswRNm3T4q9CON+bxldk2iwk3FFpuwhx2FfinyitizWHsVYyaY+y5JzDR0rCMV5yTQ== + dependencies: + pvtsutils "^1.3.2" + pvutils "^1.1.3" + tslib "^2.4.0" + assert@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/assert/-/assert-2.1.0.tgz#6d92a238d05dc02e7427c881fb8be81c8448b2dd" @@ -1936,6 +2292,11 @@ asynckit@^0.4.0: resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" integrity sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q== +at-least-node@^1.0.0: + version "1.0.0" + resolved "https://registry.npmmirror.com/at-least-node/-/at-least-node-1.0.0.tgz#602cd4b46e844ad4effc92a8011a3c46e0238dc2" + integrity sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg== + autoprefixer@^10.4.19: version "10.4.20" resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-10.4.20.tgz#5caec14d43976ef42e32dcb4bd62878e96be5b3b" @@ -1964,6 +2325,20 @@ axios@^1.6.7: form-data "^4.0.0" proxy-from-env "^1.1.0" +b64-lite@^1.3.1, b64-lite@^1.4.0: + version "1.4.0" + resolved "https://registry.npmmirror.com/b64-lite/-/b64-lite-1.4.0.tgz#e62442de11f1f21c60e38b74f111ac0242283d3d" + integrity sha512-aHe97M7DXt+dkpa8fHlCcm1CnskAHrJqEfMI0KN7dwqlzml/aUe1AGt6lk51HzrSfVD67xOso84sOpr+0wIe2w== + dependencies: + base-64 "^0.1.0" + +b64u-lite@^1.0.1: + version "1.1.0" + resolved "https://registry.npmmirror.com/b64u-lite/-/b64u-lite-1.1.0.tgz#a581b7df94cbd4bed7cbb19feae816654f0b1bf0" + integrity sha512-929qWGDVCRph7gQVTC6koHqQIpF4vtVaSbwLltFQo44B1bYUquALswZdBKFfrJCPEnsCOvWkJsPdQYZ/Ukhw8A== + dependencies: + b64-lite "^1.4.0" + babel-jest@^27.5.1: version "27.5.1" resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-27.5.1.tgz#a1bf8d61928edfefd21da27eb86a695bfd691444" @@ -2033,6 +2408,11 @@ balanced-match@^1.0.0: resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== +base-64@^0.1.0: + version "0.1.0" + resolved "https://registry.npmmirror.com/base-64/-/base-64-0.1.0.tgz#780a99c84e7d600260361511c4877613bf24f6bb" + integrity sha512-Y5gU45svrR5tI2Vt/X9GPd3L0HNIKzGu202EjxrXMpuc2V2CiKgemAbUUsqYmZJvPtCXoUKjNZwBJzsNScUbXA== + base-x@^3.0.2: version "3.0.10" resolved "https://registry.yarnpkg.com/base-x/-/base-x-3.0.10.tgz#62de58653f8762b5d6f8d9fe30fa75f7b2585a75" @@ -2040,11 +2420,28 @@ base-x@^3.0.2: dependencies: safe-buffer "^5.0.1" -base64-js@^1.3.1: +base-x@^4.0.0: + version "4.0.0" + resolved "https://registry.npmmirror.com/base-x/-/base-x-4.0.0.tgz#d0e3b7753450c73f8ad2389b5c018a4af7b2224a" + integrity sha512-FuwxlW4H5kh37X/oW59pwTzzTKRzfrrQwhmyspRM7swOEZcHtDZSCt45U6oKgtuFE+WYPblePMVIPR4RZrh/hw== + +base64-arraybuffer@^0.2.0: + version "0.2.0" + resolved "https://registry.npmmirror.com/base64-arraybuffer/-/base64-arraybuffer-0.2.0.tgz#4b944fac0191aa5907afe2d8c999ccc57ce80f45" + integrity sha512-7emyCsu1/xiBXgQZrscw/8KPRT44I4Yq9Pe6EGs3aPRTsWuggML1/1DTuZUuIaJPIm1FTDUVXl4x/yW8s0kQDQ== + +base64-js@*, base64-js@^1.3.0, base64-js@^1.3.1: version "1.5.1" resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== +bigint-buffer@^1.1.5: + version "1.1.5" + resolved "https://registry.npmmirror.com/bigint-buffer/-/bigint-buffer-1.1.5.tgz#d038f31c8e4534c1f8d0015209bf34b4fa6dd442" + integrity sha512-trfYco6AoZ+rKhKnxA0hgX0HAbVP/s808/EuDSe2JDzUnCp/xAsli35Orvk67UrTEcwuxZqYZDmfA2RXJgxVvA== + dependencies: + bindings "^1.3.0" + bigint-conversion@^2.3.0: version "2.4.3" resolved "https://registry.yarnpkg.com/bigint-conversion/-/bigint-conversion-2.4.3.tgz#cca2ff59033960be8ff517b8e931db82b6bb24fa" @@ -2057,7 +2454,7 @@ bigint-crypto-utils@^3.1.8: resolved "https://registry.yarnpkg.com/bigint-crypto-utils/-/bigint-crypto-utils-3.3.0.tgz#72ad00ae91062cf07f2b1def9594006c279c1d77" integrity sha512-jOTSb+drvEDxEq6OuUybOAv/xxoh3cuYRUIPyu8sSHQNKM303UQ2R1DAo45o1AkcIXw6fzbaFI1+xGGdaXs2lg== -bignumber.js@^9.0.1, bignumber.js@^9.1.2: +bignumber.js@^9.0.0, bignumber.js@^9.0.1, bignumber.js@^9.1.2: version "9.1.2" resolved "https://registry.yarnpkg.com/bignumber.js/-/bignumber.js-9.1.2.tgz#b7c4242259c008903b13707983b5f4bbd31eda0c" integrity sha512-2/mKyZH9K85bzOEfhXDBFZTGd1CTs+5IHpeFQo9luiBG7hghdC851Pj2WAhb6E3R6b9tZj/XKhbg4fum+Kepug== @@ -2067,21 +2464,60 @@ binary-extensions@^2.0.0: resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.3.0.tgz#f6e14a97858d327252200242d4ccfe522c445522" integrity sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw== +bindings@^1.3.0: + version "1.5.0" + resolved "https://registry.npmmirror.com/bindings/-/bindings-1.5.0.tgz#10353c9e945334bc0511a6d90b38fbc7c9c504df" + integrity sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ== + dependencies: + file-uri-to-path "1.0.0" + +bn.js@4.11.6: + version "4.11.6" + resolved "https://registry.npmmirror.com/bn.js/-/bn.js-4.11.6.tgz#53344adb14617a13f6e8dd2ce28905d1c0ba3215" + integrity sha512-XWwnNNFCuuSQ0m3r3C4LE3EiORltHd9M05pq6FOlVeiophzRbMo50Sbz1ehl8K3Z+jw9+vmgnXefY1hz8X+2wA== + bn.js@4.12.0: version "4.12.0" resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.12.0.tgz#775b3f278efbb9718eec7361f483fb36fbbfea88" integrity sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA== +bn.js@5.1.1: + version "5.1.1" + resolved "https://registry.npmmirror.com/bn.js/-/bn.js-5.1.1.tgz#48efc4031a9c4041b9c99c6941d903463ab62eb5" + integrity sha512-IUTD/REb78Z2eodka1QZyyEk66pciRcP6Sroka0aI3tG/iwIdYLrBD62RsubR7vqdt3WyX8p4jxeatzmRSphtA== + bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.11.9: version "4.12.1" resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.12.1.tgz#215741fe3c9dba2d7e12c001d0cfdbae43975ba7" integrity sha512-k8TVBiPkPJT9uHLdOKfFpqcfprwBFOAAXXozRubr7R7PfIuKvQlzcI4M0pALeqXN09vdaMbUdUj+pass+uULAg== -bn.js@^5.2.1: +bn.js@^5.2.0, bn.js@^5.2.1: version "5.2.1" resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-5.2.1.tgz#0bc527a6a0d18d0aa8d5b0538ce4a77dccfa7b70" integrity sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ== +borc@^2.1.1: + version "2.1.2" + resolved "https://registry.npmmirror.com/borc/-/borc-2.1.2.tgz#6ce75e7da5ce711b963755117dd1b187f6f8cf19" + integrity sha512-Sy9eoUi4OiKzq7VovMn246iTo17kzuyHJKomCfpWMlI6RpfN1gk95w7d7gH264nApVLg0HZfcpz62/g4VH1Y4w== + dependencies: + bignumber.js "^9.0.0" + buffer "^5.5.0" + commander "^2.15.0" + ieee754 "^1.1.13" + iso-url "~0.4.7" + json-text-sequence "~0.1.0" + readable-stream "^3.6.0" + +borsh@^0.7.0: + version "0.7.0" + resolved "https://registry.npmmirror.com/borsh/-/borsh-0.7.0.tgz#6e9560d719d86d90dc589bca60ffc8a6c51fec2a" + integrity sha512-CLCsZGIBCFnPtkNnieW/a8wmreDmfUtjU2m9yHrzPXIlNbqVs0AQrSatSG6vdNYUqdc83tkQi2eHfF98ubzQLA== + dependencies: + bn.js "^5.2.0" + bs58 "^4.0.0" + text-encoding-utf-8 "^1.0.2" + brace-expansion@^1.1.7: version "1.1.11" resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" @@ -2201,13 +2637,20 @@ bs-logger@0.x: dependencies: fast-json-stable-stringify "2.x" -bs58@^4.0.0: +bs58@^4.0.0, bs58@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/bs58/-/bs58-4.0.1.tgz#be161e76c354f6f788ae4071f63f34e8c4f0a42a" integrity sha512-Ok3Wdf5vOIlBrgCvTq96gBkJw+JUEzdBgyaza5HLtPm7yTHkjRy8+JzNyHF7BHa0bNWOQIp3m5YF0nnFcOIKLw== dependencies: base-x "^3.0.2" +bs58@^5.0.0: + version "5.0.0" + resolved "https://registry.npmmirror.com/bs58/-/bs58-5.0.0.tgz#865575b4d13c09ea2a84622df6c8cbeb54ffc279" + integrity sha512-r+ihvQJvahgYT50JD05dyJNKlmmSlMoOGwn1lCcEzanPglg7TxYjioQUYehQ9mAR/+hOSd2jRc/Z2y5UxBymvQ== + dependencies: + base-x "^4.0.0" + bs58check@<3.0.0: version "2.1.2" resolved "https://registry.yarnpkg.com/bs58check/-/bs58check-2.1.2.tgz#53b018291228d82a5aa08e7d796fdafda54aebfc" @@ -2217,6 +2660,14 @@ bs58check@<3.0.0: create-hash "^1.1.0" safe-buffer "^5.1.2" +bs58check@^3.0.1: + version "3.0.1" + resolved "https://registry.npmmirror.com/bs58check/-/bs58check-3.0.1.tgz#2094d13720a28593de1cba1d8c4e48602fdd841c" + integrity sha512-hjuuJvoWEybo7Hn/0xOrczQKKEKD63WguEjlhLExYs2wUBcebDC1jDNK17eEAD2lYfw82d5ASC1d7K3SWszjaQ== + dependencies: + "@noble/hashes" "^1.2.0" + bs58 "^5.0.0" + bser@2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/bser/-/bser-2.1.1.tgz#e6787da20ece9d07998533cfd9de6f5c38f4bc05" @@ -2234,7 +2685,15 @@ buffer-xor@^1.0.3: resolved "https://registry.yarnpkg.com/buffer-xor/-/buffer-xor-1.0.3.tgz#26e61ed1422fb70dd42e6e36729ed51d855fe8d9" integrity sha512-571s0T7nZWK6vB67HI5dyUF7wXiNcfaPPPTl6zYCNApANjIvYJTg7hlud/+cJpdAhS7dVzqMLmfhfHR3rAcOjQ== -buffer@^5.7.1: +buffer@6.0.3, buffer@^6.0.3, buffer@~6.0.3: + version "6.0.3" + resolved "https://registry.yarnpkg.com/buffer/-/buffer-6.0.3.tgz#2ace578459cc8fbe2a70aaa8f52ee63b6a74c6c6" + integrity sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA== + dependencies: + base64-js "^1.3.1" + ieee754 "^1.2.1" + +buffer@^5.5.0, buffer@^5.7.1: version "5.7.1" resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.7.1.tgz#ba62e7c13133053582197160851a8f648e99eed0" integrity sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ== @@ -2242,13 +2701,12 @@ buffer@^5.7.1: base64-js "^1.3.1" ieee754 "^1.1.13" -buffer@^6.0.3: - version "6.0.3" - resolved "https://registry.yarnpkg.com/buffer/-/buffer-6.0.3.tgz#2ace578459cc8fbe2a70aaa8f52ee63b6a74c6c6" - integrity sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA== +bufferutil@^4.0.1: + version "4.0.8" + resolved "https://registry.npmmirror.com/bufferutil/-/bufferutil-4.0.8.tgz#1de6a71092d65d7766c4d8a522b261a6e787e8ea" + integrity sha512-4T53u4PdgsXqKaIctwF8ifXlRTTmEPJ8iEPWFdGZvcf7sbwYo6FKFEX9eNNAnzFZ7EzJAQ3CJeOtCRA4rDp7Pw== dependencies: - base64-js "^1.3.1" - ieee754 "^1.2.1" + node-gyp-build "^4.3.0" builtin-status-codes@^3.0.0: version "3.0.0" @@ -2301,6 +2759,11 @@ case-anything@^2.1.13: resolved "https://registry.npmmirror.com/case-anything/-/case-anything-2.1.13.tgz#0cdc16278cb29a7fcdeb072400da3f342ba329e9" integrity sha512-zlOQ80VrQ2Ue+ymH5OuM/DlDq64mEm+B9UTdHULv5osUMD6HalNTblf2b1u/m6QecjsnOkBpqVZ+XPwIVsy7Ng== +cborg@^4.2.4: + version "4.2.7" + resolved "https://registry.npmmirror.com/cborg/-/cborg-4.2.7.tgz#19769ecaf201461eeef69ca215cf3cbda0a695bd" + integrity sha512-zHTUAm+HAoRLtGEQ1b28HXBm8d/5YP+7eiSKzEu/mpFkptGYaMQCHv15OiQBuyNlIgbCBXvBbZQPl3xvcZTJXg== + chai@^5.1.2: version "5.1.2" resolved "https://registry.yarnpkg.com/chai/-/chai-5.1.2.tgz#3afbc340b994ae3610ca519a6c70ace77ad4378d" @@ -2321,7 +2784,7 @@ chalk@^2.4.1: escape-string-regexp "^1.0.5" supports-color "^5.3.0" -chalk@^4.0.0: +chalk@^4.0.0, chalk@^4.1.0: version "4.1.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== @@ -2382,6 +2845,11 @@ cjs-module-lexer@^1.0.0: resolved "https://registry.yarnpkg.com/cjs-module-lexer/-/cjs-module-lexer-1.4.1.tgz#707413784dbb3a72aa11c2f2b042a0bef4004170" integrity sha512-cuSVIHi9/9E/+821Qjdvngor+xpnlwnuwIyZOaLmHBVdXL+gP+I6QQB9VkO7RI77YIcTV+S1W9AreJ5eN63JBA== +class-transformer@^0.5.1: + version "0.5.1" + resolved "https://registry.npmmirror.com/class-transformer/-/class-transformer-0.5.1.tgz#24147d5dffd2a6cea930a3250a677addf96ab336" + integrity sha512-SQa1Ws6hUbfC98vKGxZH3KFY0Y1lm5Zm0SY8XX9zbK7FJCyVEac3ATW0RIpwzW+oOfmHE5PMPufDG9hCfoEOMw== + cli-cursor@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-5.0.0.tgz#24a4831ecf5a6b01ddeb32fb71a4b2088b0dce38" @@ -2457,16 +2925,31 @@ combined-stream@^1.0.8: dependencies: delayed-stream "~1.0.0" +commander@^2.15.0, commander@^2.20.3: + version "2.20.3" + resolved "https://registry.npmmirror.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" + integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== + commander@^4.0.0: version "4.1.1" resolved "https://registry.yarnpkg.com/commander/-/commander-4.1.1.tgz#9fd602bd936294e9e9ef46a3f4d6964044b18068" integrity sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA== +commander@^7.2.0: + version "7.2.0" + resolved "https://registry.npmmirror.com/commander/-/commander-7.2.0.tgz#a36cb57d0b501ce108e4d20559a150a391d97ab7" + integrity sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw== + commander@~12.1.0: version "12.1.0" resolved "https://registry.yarnpkg.com/commander/-/commander-12.1.0.tgz#01423b36f501259fdaac4d0e4d60c96c991585d3" integrity sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA== +compare-versions@^3.4.0: + version "3.6.0" + resolved "https://registry.npmmirror.com/compare-versions/-/compare-versions-3.6.0.tgz#1a5689913685e5a87637b8d3ffca75514ec41d62" + integrity sha512-W6Af2Iw1z4CB7q4uU4hv646dW9GQuBM+YpC0UvUCWSD8w90SJjp+ujJuXaEMtAXBtSqGfMPuFOVn4/+FlaqfBA== + concat-map@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" @@ -2553,6 +3036,13 @@ create-require@^1.1.0, create-require@^1.1.1: resolved "https://registry.yarnpkg.com/create-require/-/create-require-1.1.1.tgz#c1d7e8f1e5f6cfc9ff65f9cd352d37348756c333" integrity sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ== +cross-fetch@^3.1.5: + version "3.1.8" + resolved "https://registry.npmmirror.com/cross-fetch/-/cross-fetch-3.1.8.tgz#0327eba65fd68a7d119f8fb2bf9334a1a7956f82" + integrity sha512-cvA+JwZoU0Xq+h6WkMvAUqPEYy92Obet6UdKLfW60qn99ftItKjB5T+BkyWOFWe2pUyfQ+IJHmpOTznqk1M6Kg== + dependencies: + node-fetch "^2.6.12" + cross-spawn@^6.0.5: version "6.0.6" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.6.tgz#30d0efa0712ddb7eb5a76e1e8721bffafa6b5d57" @@ -2742,6 +3232,11 @@ define-properties@^1.1.3, define-properties@^1.2.0, define-properties@^1.2.1: has-property-descriptors "^1.0.0" object-keys "^1.1.1" +delay@^5.0.0: + version "5.0.0" + resolved "https://registry.npmmirror.com/delay/-/delay-5.0.0.tgz#137045ef1b96e5071060dd5be60bf9334436bd1d" + integrity sha512-ReEBKkIfe4ya47wlPYf/gu5ib6yUG0/Aez0JQZQz94kiWtRQvZIQbTiehsnwHvLSWJnQdhVeqYue7Id1dKr0qw== + delayed-stream@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" @@ -2752,6 +3247,11 @@ delegates@^1.0.0: resolved "https://registry.npmmirror.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a" integrity sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ== +delimit-stream@0.1.0: + version "0.1.0" + resolved "https://registry.npmmirror.com/delimit-stream/-/delimit-stream-0.1.0.tgz#9b8319477c0e5f8aeb3ce357ae305fc25ea1cd2b" + integrity sha512-a02fiQ7poS5CnjiJBAsjGLPp5EwVoGHNeu9sziBd9huppRfsAFIpv5zNLv0V1gbop53ilngAf5Kf331AwcoRBQ== + des.js@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/des.js/-/des.js-1.1.0.tgz#1d37f5766f3bbff4ee9638e871a8768c173b81da" @@ -2990,6 +3490,18 @@ es-to-primitive@^1.2.1: is-date-object "^1.0.5" is-symbol "^1.0.4" +es6-promise@^4.0.3: + version "4.2.8" + resolved "https://registry.npmmirror.com/es6-promise/-/es6-promise-4.2.8.tgz#4eb21594c972bc40553d276e510539143db53e0a" + integrity sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w== + +es6-promisify@^5.0.0: + version "5.0.0" + resolved "https://registry.npmmirror.com/es6-promisify/-/es6-promisify-5.0.0.tgz#5109d62f3e56ea967c4b63505aef08291c8a5203" + integrity sha512-C+d6UdsYDk0lMebHNR4S2NybQMMngAOnOwYBQjTOiv0MkoJMP0Myw2mgpDLBcpfCmRLxyFqYhS/CfOENq4SJhQ== + dependencies: + es6-promise "^4.0.3" + esbuild@^0.21.3: version "0.21.5" resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.21.5.tgz#9ca301b120922959b766360d8ac830da0d02997d" @@ -3211,6 +3723,14 @@ ethers@^6.13.1: tslib "2.7.0" ws "8.17.1" +ethjs-unit@0.1.6: + version "0.1.6" + resolved "https://registry.npmmirror.com/ethjs-unit/-/ethjs-unit-0.1.6.tgz#c665921e476e87bce2a9d588a6fe0405b2c41699" + integrity sha512-/Sn9Y0oKl0uqQuvgFk/zQgR7aw1g36qX/jzSQ5lSwlO0GigPymk4eGQfeNTD03w1dPOqfz8V77Cy43jH56pagw== + dependencies: + bn.js "4.11.6" + number-to-bn "1.7.0" + eventemitter3@^3.1.0: version "3.1.2" resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-3.1.2.tgz#2d3d48f9c346698fce83a85d7d664e98535df6e7" @@ -3221,7 +3741,7 @@ eventemitter3@^5.0.1: resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-5.0.1.tgz#53f5ffd0a492ac800721bb42c66b841de96423c4" integrity sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA== -events@^3.0.0: +events@^3.0.0, events@^3.3.0: version "3.3.0" resolved "https://registry.yarnpkg.com/events/-/events-3.3.0.tgz#31a95ad0a924e2d2c419a813aeb2c4e878ea7400" integrity sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q== @@ -3284,12 +3804,35 @@ expect@^27.5.1: jest-matcher-utils "^27.5.1" jest-message-util "^27.5.1" +expo-modules-autolinking@^0.0.3: + version "0.0.3" + resolved "https://registry.npmmirror.com/expo-modules-autolinking/-/expo-modules-autolinking-0.0.3.tgz#45ba8cb1798f9339347ae35e96e9cc70eafb3727" + integrity sha512-azkCRYj/DxbK4udDuDxA9beYzQTwpJ5a9QA0bBgha2jHtWdFGF4ZZWSY+zNA5mtU3KqzYt8jWHfoqgSvKyu1Aw== + dependencies: + chalk "^4.1.0" + commander "^7.2.0" + fast-glob "^3.2.5" + find-up "~5.0.0" + fs-extra "^9.1.0" + +expo-random@*: + version "14.0.1" + resolved "https://registry.npmmirror.com/expo-random/-/expo-random-14.0.1.tgz#aedc6a3b6ff86c74a85989d77d20e0f1762ed669" + integrity sha512-gX2mtR9o+WelX21YizXUCD/y+a4ZL+RDthDmFkHxaYbdzjSYTn8u/igoje/l3WEO+/RYspmqUFa8w/ckNbt6Vg== + dependencies: + base64-js "^1.3.0" + +eyes@^0.1.8: + version "0.1.8" + resolved "https://registry.npmmirror.com/eyes/-/eyes-0.1.8.tgz#62cf120234c683785d902348a800ef3e0cc20bc0" + integrity sha512-GipyPsXO1anza0AOZdy69Im7hGFCNB7Y/NGjDlZGJ3GJJLtwNSb2vrzYrTYJRrRloVx7pl+bhUaTB8yiccPvFQ== + fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: version "3.1.3" resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== -fast-glob@^3.3.2: +fast-glob@^3.2.5, fast-glob@^3.3.2: version "3.3.2" resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.3.2.tgz#a904501e57cfdd2ffcded45e99a54fef55e46129" integrity sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow== @@ -3310,6 +3853,11 @@ fast-levenshtein@^2.0.6: resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" integrity sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw== +fast-stable-stringify@^1.0.0: + version "1.0.0" + resolved "https://registry.npmmirror.com/fast-stable-stringify/-/fast-stable-stringify-1.0.0.tgz#5c5543462b22aeeefd36d05b34e51c78cb86d313" + integrity sha512-wpYMUmFu5f00Sm0cj2pfivpmawLZ0NKdviQ4w9zJeR8JVtOpOxHmLaJuj0vxvGqMJQWyP/COUkF75/57OKyRag== + fastparse@^1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/fastparse/-/fastparse-1.1.2.tgz#91728c5a5942eced8531283c79441ee4122c35a9" @@ -3336,6 +3884,11 @@ file-entry-cache@^8.0.0: dependencies: flat-cache "^4.0.0" +file-uri-to-path@1.0.0: + version "1.0.0" + resolved "https://registry.npmmirror.com/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz#553a7b8446ff6f684359c445f1e37a05dacc33dd" + integrity sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw== + fill-range@^7.1.1: version "7.1.1" resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.1.1.tgz#44265d3cac07e3ea7dc247516380643754a05292" @@ -3351,7 +3904,7 @@ find-up@^4.0.0, find-up@^4.1.0: locate-path "^5.0.0" path-exists "^4.0.0" -find-up@^5.0.0: +find-up@^5.0.0, find-up@~5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/find-up/-/find-up-5.0.0.tgz#4c92819ecb7083561e4f4a240a86be5198f536fc" integrity sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng== @@ -3415,6 +3968,16 @@ fraction.js@^4.3.7: resolved "https://registry.yarnpkg.com/fraction.js/-/fraction.js-4.3.7.tgz#06ca0085157e42fda7f9e726e79fefc4068840f7" integrity sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew== +fs-extra@^9.1.0: + version "9.1.0" + resolved "https://registry.npmmirror.com/fs-extra/-/fs-extra-9.1.0.tgz#5954460c764a8da2094ba3554bf839e6b9a7c86d" + integrity sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ== + dependencies: + at-least-node "^1.0.0" + graceful-fs "^4.2.0" + jsonfile "^6.0.1" + universalify "^2.0.0" + fs-minipass@^2.0.0: version "2.1.0" resolved "https://registry.npmmirror.com/fs-minipass/-/fs-minipass-2.1.0.tgz#7f5036fdbf12c63c169190cbe4199c852271f9fb" @@ -3585,7 +4148,7 @@ gopd@^1.0.1, gopd@^1.1.0: dependencies: get-intrinsic "^1.2.4" -graceful-fs@^4.1.2, graceful-fs@^4.2.9: +graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.9: version "4.2.11" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3" integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== @@ -3736,11 +4299,29 @@ human-signals@^5.0.0: resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-5.0.0.tgz#42665a284f9ae0dade3ba41ebc37eb4b852f3a28" integrity sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ== +humanize-ms@^1.2.1: + version "1.2.1" + resolved "https://registry.npmmirror.com/humanize-ms/-/humanize-ms-1.2.1.tgz#c46e3159a293f6b896da29316d8b6fe8bb79bbed" + integrity sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ== + dependencies: + ms "^2.0.0" + husky@^9.0.0: version "9.1.7" resolved "https://registry.yarnpkg.com/husky/-/husky-9.1.7.tgz#d46a38035d101b46a70456a850ff4201344c0b2d" integrity sha512-5gs5ytaNjBrh5Ow3zrvdUUY+0VxIuWVL4i9irt6friV+BqdCfmV11CQTWMiBYWHbXhco+J1kHfTOUkePhCDvMA== +ic0@^0.2.8: + version "0.2.8" + resolved "https://registry.npmmirror.com/ic0/-/ic0-0.2.8.tgz#9864d4926444c433960d6d454a8bf5c1b7a13149" + integrity sha512-IPtyrB79fvlb9uQcI8dlKDBsqc1eyCckMDsKzgbaiURrM/bVnDJaZ+dsB1CXxQNpsmb/qV3DXPXJRAhh6AVh3w== + dependencies: + "@dfinity/agent" "^0.19.2" + "@dfinity/candid" "^0.19.2" + "@dfinity/identity" "^0.19.2" + "@dfinity/principal" "^0.19.2" + cross-fetch "^3.1.5" + iconv-lite@0.4.24: version "0.4.24" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" @@ -3801,6 +4382,13 @@ internal-slot@^1.0.7: hasown "^2.0.0" side-channel "^1.0.4" +invariant@^2.2.4: + version "2.2.4" + resolved "https://registry.npmmirror.com/invariant/-/invariant-2.2.4.tgz#610f3c92c9359ce1db616e538008d23ff35158e6" + integrity sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA== + dependencies: + loose-envify "^1.0.0" + is-arguments@^1.0.4: version "1.1.1" resolved "https://registry.yarnpkg.com/is-arguments/-/is-arguments-1.1.1.tgz#15b3f88fda01f2a97fec84ca761a560f123efa9b" @@ -3925,6 +4513,11 @@ is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3, is-glob@~4.0.1: dependencies: is-extglob "^2.1.1" +is-hex-prefixed@1.0.0: + version "1.0.0" + resolved "https://registry.npmmirror.com/is-hex-prefixed/-/is-hex-prefixed-1.0.0.tgz#7d8d37e6ad77e5d127148913c573e082d777f554" + integrity sha512-WvtOiug1VFrE9v1Cydwm+FnXd3+w9GaeVUss5W4v/SLy3UW00vP+6iNF2SdnfiBoLy4bTqVdkftNGTUeOFVsbA== + is-map@^2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/is-map/-/is-map-2.0.3.tgz#ede96b7fe1e270b3c4465e3a465658764926d62e" @@ -4053,11 +4646,47 @@ isexe@^2.0.0: resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== +iso-url@~0.4.7: + version "0.4.7" + resolved "https://registry.npmmirror.com/iso-url/-/iso-url-0.4.7.tgz#de7e48120dae46921079fe78f325ac9e9217a385" + integrity sha512-27fFRDnPAMnHGLq36bWTpKET+eiXct3ENlCcdcMdk+mjXrb2kw3mhBUg1B7ewAC0kVzlOPhADzQgz1SE6Tglog== + +isomorphic-fetch@^3.0.0: + version "3.0.0" + resolved "https://registry.npmmirror.com/isomorphic-fetch/-/isomorphic-fetch-3.0.0.tgz#0267b005049046d2421207215d45d6a262b8b8b4" + integrity sha512-qvUtwJ3j6qwsF3jLxkZ72qCgjMysPzDfeV240JHiGZsANBYd+EEuu35v7dfrJ9Up0Ak07D7GGSkGhCHTqg/5wA== + dependencies: + node-fetch "^2.6.1" + whatwg-fetch "^3.4.1" + isomorphic-timers-promises@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/isomorphic-timers-promises/-/isomorphic-timers-promises-1.0.1.tgz#e4137c24dbc54892de8abae3a4b5c1ffff381598" integrity sha512-u4sej9B1LPSxTGKB/HiuzvEQnXH0ECYkSVQU39koSwmFAxhlEAFl9RdTvLv4TOTQUgBS5O3O5fwUxk6byBZ+IQ== +isomorphic-webcrypto@2.3.8: + version "2.3.8" + resolved "https://registry.npmmirror.com/isomorphic-webcrypto/-/isomorphic-webcrypto-2.3.8.tgz#4a7493b486ef072b9f11b6f8fd66adde856e3eec" + integrity sha512-XddQSI0WYlSCjxtm1AI8kWQOulf7hAN3k3DclF1sxDJZqOe0pcsOt675zvWW91cZH9hYs3nlA3Ev8QK5i80SxQ== + dependencies: + "@peculiar/webcrypto" "^1.0.22" + asmcrypto.js "^0.22.0" + b64-lite "^1.3.1" + b64u-lite "^1.0.1" + msrcrypto "^1.5.6" + str2buf "^1.3.0" + webcrypto-shim "^0.1.4" + optionalDependencies: + "@unimodules/core" "*" + "@unimodules/react-native-adapter" "*" + expo-random "*" + react-native-securerandom "^0.1.1" + +isomorphic-ws@^4.0.1: + version "4.0.1" + resolved "https://registry.npmmirror.com/isomorphic-ws/-/isomorphic-ws-4.0.1.tgz#55fd4cd6c5e6491e76dc125938dd863f5cd4f2dc" + integrity sha512-BhBvN2MBpWTaSHdWRb/bwdZJ1WaehQ2L1KngkCkfLUGF0mAWAT1sQUQacEmQ0jXkFw/czDXPNQSL5u2/Krsz1w== + isomorphic-ws@^5.0.0: version "5.0.0" resolved "https://registry.npmmirror.com/isomorphic-ws/-/isomorphic-ws-5.0.0.tgz#e5529148912ecb9b451b46ed44d53dae1ce04bbf" @@ -4114,6 +4743,24 @@ jackspeak@^3.1.2: optionalDependencies: "@pkgjs/parseargs" "^0.11.0" +jayson@^4.1.1: + version "4.1.3" + resolved "https://registry.npmmirror.com/jayson/-/jayson-4.1.3.tgz#db9be2e4287d9fef4fc05b5fe367abe792c2eee8" + integrity sha512-LtXh5aYZodBZ9Fc3j6f2w+MTNcnxteMOrb+QgIouguGOulWi0lieEkOUg+HkjjFs0DGoWDds6bi4E9hpNFLulQ== + dependencies: + "@types/connect" "^3.4.33" + "@types/node" "^12.12.54" + "@types/ws" "^7.4.4" + JSONStream "^1.3.5" + commander "^2.20.3" + delay "^5.0.0" + es6-promisify "^5.0.0" + eyes "^0.1.8" + isomorphic-ws "^4.0.1" + json-stringify-safe "^5.0.1" + uuid "^8.3.2" + ws "^7.5.10" + jest-changed-files@^27.5.1: version "27.5.1" resolved "https://registry.yarnpkg.com/jest-changed-files/-/jest-changed-files-27.5.1.tgz#a348aed00ec9bf671cc58a66fcbe7c3dfd6a68f5" @@ -4529,7 +5176,7 @@ js-base64@^3.7.2: resolved "https://registry.npmmirror.com/js-base64/-/js-base64-3.7.7.tgz#e51b84bf78fbf5702b9541e2cb7bfcb893b43e79" integrity sha512-7rCnleh0z2CkXhH67J8K1Ytz0b2Y+yxTPL+/KOJoa20hfnVQ/3/T6W/KflYI4bRHRagNeXeU2bkNGI3v1oS/lw== -js-tokens@^4.0.0: +"js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== @@ -4612,16 +5259,47 @@ json-stable-stringify-without-jsonify@^1.0.1: resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" integrity sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw== +json-stringify-safe@^5.0.1: + version "5.0.1" + resolved "https://registry.npmmirror.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" + integrity sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA== + +json-text-sequence@~0.1.0: + version "0.1.1" + resolved "https://registry.npmmirror.com/json-text-sequence/-/json-text-sequence-0.1.1.tgz#a72f217dc4afc4629fff5feb304dc1bd51a2f3d2" + integrity sha512-L3mEegEWHRekSHjc7+sc8eJhba9Clq1PZ8kMkzf8OxElhXc8O4TS5MwcVlj9aEbm5dr81N90WHC5nAz3UO971w== + dependencies: + delimit-stream "0.1.0" + json5@2.x, json5@^2.2.3: version "2.2.3" resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.3.tgz#78cd6f1a19bdc12b73db5ad0c61efd66c1e29283" integrity sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg== +jsonfile@^6.0.1: + version "6.1.0" + resolved "https://registry.npmmirror.com/jsonfile/-/jsonfile-6.1.0.tgz#bc55b2634793c679ec6403094eb13698a6ec0aae" + integrity sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ== + dependencies: + universalify "^2.0.0" + optionalDependencies: + graceful-fs "^4.1.6" + +jsonparse@^1.2.0: + version "1.3.1" + resolved "https://registry.npmmirror.com/jsonparse/-/jsonparse-1.3.1.tgz#3f4dae4a91fac315f71062f8521cc239f1366280" + integrity sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg== + jssha@3.2.0: version "3.2.0" resolved "https://registry.yarnpkg.com/jssha/-/jssha-3.2.0.tgz#88ec50b866dd1411deaddbe6b3e3692e4c710f16" integrity sha512-QuruyBENDWdN4tZwJbQq7/eAK85FqrI4oDbXjy5IBhYD+2pTJyBUWZe8ctWaCkrV0gy6AaelgOZZBMeswEa/6Q== +jssha@^3.3.0: + version "3.3.1" + resolved "https://registry.npmmirror.com/jssha/-/jssha-3.3.1.tgz#c5b7fc7fb9aa745461923b87df0e247dd59c7ea8" + integrity sha512-VCMZj12FCFMQYcFLPRm/0lOBbLi8uM2BhXPTqw3U4YAfs4AZfiApOoBLoN8cQE60Z50m1MYMTQVCfgF/KaCVhQ== + keyv@^4.5.4: version "4.5.4" resolved "https://registry.yarnpkg.com/keyv/-/keyv-4.5.4.tgz#a879a99e29452f942439f2a405e3af8b31d4de93" @@ -4745,6 +5423,13 @@ long@^5.0.0, long@^5.2.0, long@^5.2.3: resolved "https://registry.yarnpkg.com/long/-/long-5.2.3.tgz#a3ba97f3877cf1d778eccbcb048525ebb77499e1" integrity sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q== +loose-envify@^1.0.0: + version "1.4.0" + resolved "https://registry.npmmirror.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf" + integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q== + dependencies: + js-tokens "^3.0.0 || ^4.0.0" + loupe@^3.1.0, loupe@^3.1.2: version "3.1.2" resolved "https://registry.yarnpkg.com/loupe/-/loupe-3.1.2.tgz#c86e0696804a02218f2206124c45d8b15291a240" @@ -4923,11 +5608,16 @@ mkdirp@^1.0.3: resolved "https://registry.npmmirror.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e" integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw== -ms@^2.1.3: +ms@^2.0.0, ms@^2.1.3: version "2.1.3" resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== +msrcrypto@^1.5.6: + version "1.5.8" + resolved "https://registry.npmmirror.com/msrcrypto/-/msrcrypto-1.5.8.tgz#be419be4945bf134d8af52e9d43be7fa261f4a1c" + integrity sha512-ujZ0TRuozHKKm6eGbKHfXef7f+esIhEckmThVnz7RNyiOJd7a6MXj2JGBoL9cnPDW+JMG16MoTUh5X+XXjI66Q== + mz@^2.7.0: version "2.7.0" resolved "https://registry.yarnpkg.com/mz/-/mz-2.7.0.tgz#95008057a56cafadc2bc63dde7f9ff6955948e32" @@ -4977,13 +5667,25 @@ no-case@^3.0.4: lower-case "^2.0.2" tslib "^2.0.3" -node-fetch@^2.6.7: +node-fetch@2.6.7: + version "2.6.7" + resolved "https://registry.npmmirror.com/node-fetch/-/node-fetch-2.6.7.tgz#24de9fba827e3b4ae44dc8b20256a379160052ad" + integrity sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ== + dependencies: + whatwg-url "^5.0.0" + +node-fetch@^2.6.1, node-fetch@^2.6.12, node-fetch@^2.6.7, node-fetch@^2.7.0: version "2.7.0" resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.7.0.tgz#d0f0fa6e3e2dc1d27efcd8ad99d550bda94d187d" integrity sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A== dependencies: whatwg-url "^5.0.0" +node-gyp-build@^4.3.0: + version "4.8.4" + resolved "https://registry.npmmirror.com/node-gyp-build/-/node-gyp-build-4.8.4.tgz#8a70ee85464ae52327772a90d66c6077a900cfc8" + integrity sha512-LA4ZjwlnUblHVgq0oBF3Jl/6h/Nvs5fzBLwdEF4nuxnFdsfajde4WfxtJr3CaiH+F6ewcIB/q4jQ4UzPyid+CQ== + node-int64@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/node-int64/-/node-int64-0.4.0.tgz#87a9065cdb355d3182d8f94ce11188b825c68a3b" @@ -5093,6 +5795,14 @@ npmlog@^5.0.1: gauge "^3.0.0" set-blocking "^2.0.0" +number-to-bn@1.7.0: + version "1.7.0" + resolved "https://registry.npmmirror.com/number-to-bn/-/number-to-bn-1.7.0.tgz#bb3623592f7e5f9e0030b1977bd41a0c53fe1ea0" + integrity sha512-wsJ9gfSz1/s4ZsJN01lyonwuxA1tml6X1yBDnfpMglypcBRFZZkus26EdPSlqS5GJfYddVZa22p3VNb3z5m5Ig== + dependencies: + bn.js "4.11.6" + strip-hex-prefix "1.0.0" + nwsapi@^2.2.0: version "2.2.16" resolved "https://registry.yarnpkg.com/nwsapi/-/nwsapi-2.2.16.tgz#177760bba02c351df1d2644e220c31dfec8cdb43" @@ -5548,6 +6258,18 @@ punycode@^2.1.0, punycode@^2.1.1, punycode@^2.3.1: resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.1.tgz#027422e2faec0b25e1549c3e1bd8309b9133b6e5" integrity sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg== +pvtsutils@^1.3.2, pvtsutils@^1.3.5: + version "1.3.6" + resolved "https://registry.npmmirror.com/pvtsutils/-/pvtsutils-1.3.6.tgz#ec46e34db7422b9e4fdc5490578c1883657d6001" + integrity sha512-PLgQXQ6H2FWCaeRak8vvk1GW462lMxB5s3Jm673N82zI4vqtVUPuZdffdZbPDFRoU8kAhItWFtPCWiPpp4/EDg== + dependencies: + tslib "^2.8.1" + +pvutils@^1.1.3: + version "1.1.3" + resolved "https://registry.npmmirror.com/pvutils/-/pvutils-1.1.3.tgz#f35fc1d27e7cd3dfbd39c0826d173e806a03f5a3" + integrity sha512-pMpnA0qRdFp32b1sJl1wOJNxZLQ2cbQx+k6tjNtZ8CpvVhNqEPRgivZ2WOUev2YMajecdH7ctUPDvEe87nariQ== + qs@^6.12.3: version "6.13.1" resolved "https://registry.yarnpkg.com/qs/-/qs-6.13.1.tgz#3ce5fc72bd3a8171b85c99b93c65dd20b7d1b16e" @@ -5597,6 +6319,13 @@ react-is@^17.0.1: resolved "https://registry.yarnpkg.com/react-is/-/react-is-17.0.2.tgz#e691d4a8e9c789365655539ab372762b0efb54f0" integrity sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w== +react-native-securerandom@^0.1.1: + version "0.1.1" + resolved "https://registry.npmmirror.com/react-native-securerandom/-/react-native-securerandom-0.1.1.tgz#f130623a412c338b0afadedbc204c5cbb8bf2070" + integrity sha512-CozcCx0lpBLevxiXEb86kwLRalBCHNjiGPlw3P7Fi27U6ZLdfjOCNRHD1LtBKcvPvI3TvkBXB3GOtLvqaYJLGw== + dependencies: + base64-js "*" + react-refresh@^0.14.2: version "0.14.2" resolved "https://registry.yarnpkg.com/react-refresh/-/react-refresh-0.14.2.tgz#3833da01ce32da470f1f936b9d477da5c7028bf9" @@ -5669,6 +6398,11 @@ readdirp@~3.6.0: dependencies: picomatch "^2.2.1" +reflect-metadata@^0.2.2: + version "0.2.2" + resolved "https://registry.npmmirror.com/reflect-metadata/-/reflect-metadata-0.2.2.tgz#400c845b6cba87a21f2c65c4aeb158f4fa4d9c5b" + integrity sha512-urBwgfrvVP/eAyXx4hluJivBKzuEbSQs9rKWCrCkbSxNv8mxPcUZKeuoF3Uy4mJl3Lwprp6yy5/39VWigZ4K6Q== + reflect.getprototypeof@^1.0.6: version "1.0.7" resolved "https://registry.yarnpkg.com/reflect.getprototypeof/-/reflect.getprototypeof-1.0.7.tgz#04311b33a1b713ca5eb7b5aed9950a86481858e5" @@ -5682,6 +6416,11 @@ reflect.getprototypeof@^1.0.6: gopd "^1.0.1" which-builtin-type "^1.1.4" +regenerator-runtime@^0.14.0: + version "0.14.1" + resolved "https://registry.npmmirror.com/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz#356ade10263f685dda125100cd862c1db895327f" + integrity sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw== + regexp.prototype.flags@^1.5.3: version "1.5.3" resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.5.3.tgz#b3ae40b1d2499b8350ab2c3fe6ef3845d3a96f42" @@ -5793,6 +6532,22 @@ rollup@^4.20.0, rollup@^4.23.0: "@rollup/rollup-win32-x64-msvc" "4.28.0" fsevents "~2.3.2" +rpc-websockets@^9.0.2: + version "9.0.4" + resolved "https://registry.npmmirror.com/rpc-websockets/-/rpc-websockets-9.0.4.tgz#9d8ee82533b5d1e13d9ded729e3e38d0d8fa083f" + integrity sha512-yWZWN0M+bivtoNLnaDbtny4XchdAIF5Q4g/ZsC5UC61Ckbp0QczwO8fg44rV3uYmY4WHd+EZQbn90W1d8ojzqQ== + dependencies: + "@swc/helpers" "^0.5.11" + "@types/uuid" "^8.3.4" + "@types/ws" "^8.2.2" + buffer "^6.0.3" + eventemitter3 "^5.0.1" + uuid "^8.3.2" + ws "^8.5.0" + optionalDependencies: + bufferutil "^4.0.1" + utf-8-validate "^5.0.2" + run-parallel@^1.1.9: version "1.2.0" resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.2.0.tgz#66d1368da7bdf921eb9d95bd1a9229e7f21a43ee" @@ -5800,6 +6555,13 @@ run-parallel@^1.1.9: dependencies: queue-microtask "^1.2.2" +rxjs@6, rxjs@^6.6.7: + version "6.6.7" + resolved "https://registry.npmmirror.com/rxjs/-/rxjs-6.6.7.tgz#90ac018acabf491bf65044235d5863c4dab804c9" + integrity sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ== + dependencies: + tslib "^1.9.0" + safe-array-concat@^1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/safe-array-concat/-/safe-array-concat-1.1.2.tgz#81d77ee0c4e8b863635227c721278dd524c20edb" @@ -5960,6 +6722,11 @@ signal-exit@^4.0.1, signal-exit@^4.1.0: resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-4.1.0.tgz#952188c1cbd546070e2dd20d0f41c0ae0530cb04" integrity sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw== +simple-cbor@^0.4.1: + version "0.4.1" + resolved "https://registry.npmmirror.com/simple-cbor/-/simple-cbor-0.4.1.tgz#0c88312e87db52b94e0e92f6bd1cf634e86f8a22" + integrity sha512-rijcxtwx2b4Bje3sqeIqw5EeW7UlOIC4YfOdwqIKacpvRQ/D78bWg/4/0m5e0U91oKvlGh7LlJuZCu07ISCC7w== + sisteransi@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/sisteransi/-/sisteransi-1.0.5.tgz#134d681297756437cc05ca01370d3a7a571075ed" @@ -6065,6 +6832,11 @@ std-env@^3.8.0: resolved "https://registry.yarnpkg.com/std-env/-/std-env-3.8.0.tgz#b56ffc1baf1a29dcc80a3bdf11d7fca7c315e7d5" integrity sha512-Bc3YwwCB+OzldMxOXJIIvC6cPRWr/LxOp48CdQTOkPyk/t4JWWJbrilwBd7RJzKV8QW7tJkcgAmeuLLJugl5/w== +str2buf@^1.3.0: + version "1.3.0" + resolved "https://registry.npmmirror.com/str2buf/-/str2buf-1.3.0.tgz#a4172afff4310e67235178e738a2dbb573abead0" + integrity sha512-xIBmHIUHYZDP4HyoXGHYNVmxlXLXDrtFHYT0eV6IOdEj3VO9ccaF1Ejl9Oq8iFjITllpT8FhaXb4KsNmw+3EuA== + stream-browserify@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/stream-browserify/-/stream-browserify-3.0.0.tgz#22b0a2850cdf6503e73085da1fc7b7d0c2122f2f" @@ -6225,6 +6997,13 @@ strip-final-newline@^3.0.0: resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-3.0.0.tgz#52894c313fbff318835280aed60ff71ebf12b8fd" integrity sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw== +strip-hex-prefix@1.0.0: + version "1.0.0" + resolved "https://registry.npmmirror.com/strip-hex-prefix/-/strip-hex-prefix-1.0.0.tgz#0c5f155fef1151373377de9dbb588da05500e36f" + integrity sha512-q8d4ue7JGEiVcypji1bALTos+0pWtyGlivAWyPuTkHzuTCJqrK9sWxYQZUq6Nq3cuyv3bm734IhHvHtGGURU6A== + dependencies: + is-hex-prefixed "1.0.0" + strip-json-comments@^3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" @@ -6243,6 +7022,11 @@ sucrase@^3.35.0: pirates "^4.0.1" ts-interface-checker "^0.1.9" +superstruct@^2.0.2: + version "2.0.2" + resolved "https://registry.npmmirror.com/superstruct/-/superstruct-2.0.2.tgz#3f6d32fbdc11c357deff127d591a39b996300c54" + integrity sha512-uV+TFRZdXsqXTL2pRvujROjdZQ4RAlBUS5BTh9IGm+jTqQntYThciG/qu57Gs69yjnVUSqdxF9YLmSnpupBW9A== + supports-color@^5.3.0: version "5.5.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" @@ -6359,6 +7143,11 @@ test-exclude@^6.0.0: glob "^7.1.4" minimatch "^3.0.4" +text-encoding-utf-8@^1.0.2: + version "1.0.2" + resolved "https://registry.npmmirror.com/text-encoding-utf-8/-/text-encoding-utf-8-1.0.2.tgz#585b62197b0ae437e3c7b5d0af27ac1021e10d13" + integrity sha512-8bw4MY9WjdsD2aMtO0OzOCY3pXGYNx2d2FfHRVUKkiCPDWjKuOlhLVASS+pD7VkLTVjW268LYJHwsnPFlBpbAg== + thenify-all@^1.0.0: version "1.6.0" resolved "https://registry.yarnpkg.com/thenify-all/-/thenify-all-1.6.0.tgz#1a1918d402d8fc3f98fbf234db0bcc8cc10e9726" @@ -6378,6 +7167,11 @@ throat@^6.0.1: resolved "https://registry.yarnpkg.com/throat/-/throat-6.0.2.tgz#51a3fbb5e11ae72e2cf74861ed5c8020f89f29fe" integrity sha512-WKexMoJj3vEuK0yFEapj8y64V0A6xcuPuK9Gt1d0R+dzCSJc0lHqQytAbSB4cDAK0dWh4T0E2ETkoLE2WZ41OQ== +"through@>=2.2.7 <3": + version "2.3.8" + resolved "https://registry.npmmirror.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" + integrity sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg== + timers-browserify@^2.0.4: version "2.0.12" resolved "https://registry.yarnpkg.com/timers-browserify/-/timers-browserify-2.0.12.tgz#44a45c11fbf407f34f97bccd1577c652361b00ee" @@ -6427,6 +7221,27 @@ toml@^3.0.0: resolved "https://registry.yarnpkg.com/toml/-/toml-3.0.0.tgz#342160f1af1904ec9d204d03a5d61222d762c5ee" integrity sha512-y/mWCZinnvxjTKYhJ+pYxwD0mRLVvOtdS2Awbgxln6iEnt4rk0yBxeSBHkGJcPucRiG0e55mwWp+g/05rsrd6w== +tonweb-mnemonic@^1.0.1: + version "1.0.1" + resolved "https://registry.npmmirror.com/tonweb-mnemonic/-/tonweb-mnemonic-1.0.1.tgz#bb1b8bb6220f56f8e230b8a8f9555ff5bcbd4681" + integrity sha512-YQAEXQHBHb0dnNy50bwIutXwyWa6Den7+cLcXWoG7ZClcqo4bjALOr6tnIqI+hs5jab+AGSsRjilxcp8ao/CpA== + dependencies: + tweetnacl "^1.0.3" + +tonweb@^0.0.66: + version "0.0.66" + resolved "https://registry.npmmirror.com/tonweb/-/tonweb-0.0.66.tgz#e9aa1f81ac2c2a9b0ff692294d58b1dfea516fb4" + integrity sha512-ntDJU1b/kgMFvOYN09FvhdnAfwnZh8W5sONkUP+P0FQkYRa/027otRxApp5gfxZ9DR+3WTnCQgrsG/EXv8RhEA== + dependencies: + "@ledgerhq/hw-transport-web-ble" "5.48.0" + "@ledgerhq/hw-transport-webhid" "5.48.0" + "@ledgerhq/hw-transport-webusb" "5.48.0" + bn.js "5.1.1" + ethjs-unit "0.1.6" + isomorphic-webcrypto "2.3.8" + node-fetch "2.6.7" + tweetnacl "1.0.3" + tough-cookie@^4.0.0: version "4.1.4" resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-4.1.4.tgz#945f1461b45b5a8c76821c33ea49c3ac192c1b36" @@ -6526,7 +7341,12 @@ tslib@2.7.0: resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.7.0.tgz#d9b40c5c40ab59e8738f297df3087bf1a2690c01" integrity sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA== -tslib@^2.0.3: +tslib@^1.9.0: + version "1.14.1" + resolved "https://registry.npmmirror.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" + integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== + +tslib@^2.0.0, tslib@^2.0.3, tslib@^2.4.0, tslib@^2.6.2, tslib@^2.7.0, tslib@^2.8.0, tslib@^2.8.1: version "2.8.1" resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.8.1.tgz#612efe4ed235d567e8aba5f2a5fab70280ade83f" integrity sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w== @@ -6588,7 +7408,7 @@ tweetnacl-util@^0.15.1: resolved "https://registry.yarnpkg.com/tweetnacl-util/-/tweetnacl-util-0.15.1.tgz#b80fcdb5c97bcc508be18c44a4be50f022eea00b" integrity sha512-RKJBIj8lySrShN4w6i/BonWp2Z/uxwC3h4y7xsRrpP59ZboCd0GpEVsOnMDYLMmKBpYhb5TgHzZXy7wTfYFBRw== -tweetnacl@1.0.3, tweetnacl@^1.0.3: +tweetnacl@1.0.3, tweetnacl@^1.0.1, tweetnacl@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-1.0.3.tgz#ac0af71680458d8a6378d0d0d050ab1407d35596" integrity sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw== @@ -6716,6 +7536,11 @@ universalify@^0.2.0: resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.2.0.tgz#6451760566fa857534745ab1dde952d1b1761be0" integrity sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg== +universalify@^2.0.0: + version "2.0.1" + resolved "https://registry.npmmirror.com/universalify/-/universalify-2.0.1.tgz#168efc2180964e6386d061e094df61afe239b18d" + integrity sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw== + update-browserslist-db@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.1.1.tgz#80846fba1d79e82547fb661f8d141e0945755fe5" @@ -6747,6 +7572,13 @@ url@^0.11.4: punycode "^1.4.1" qs "^6.12.3" +utf-8-validate@^5.0.2: + version "5.0.10" + resolved "https://registry.npmmirror.com/utf-8-validate/-/utf-8-validate-5.0.10.tgz#d7d10ea39318171ca982718b6b96a8d2442571a2" + integrity sha512-Z6czzLq4u8fPOyx7TU6X3dvUZVvoJmxSQ+IcrlmagKhilxlhZgxPK6C5Jqbkw1IDUmFTM+cz9QDnnLTwDz/2gQ== + dependencies: + node-gyp-build "^4.3.0" + util-deprecate@^1.0.1, util-deprecate@^1.0.2, util-deprecate@~1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" @@ -6763,6 +7595,11 @@ util@^0.12.4, util@^0.12.5: is-typed-array "^1.1.3" which-typed-array "^1.1.2" +uuid@^8.3.2: + version "8.3.2" + resolved "https://registry.npmmirror.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2" + integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg== + v8-compile-cache-lib@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz#6336e8d71965cb3d35a1bbb7868445a7c05264bf" @@ -6892,6 +7729,22 @@ walker@^1.0.7: dependencies: makeerror "1.0.12" +webcrypto-core@^1.8.0: + version "1.8.1" + resolved "https://registry.npmmirror.com/webcrypto-core/-/webcrypto-core-1.8.1.tgz#09d5bd8a9c48e9fbcaf412e06b1ff1a57514ce86" + integrity sha512-P+x1MvlNCXlKbLSOY4cYrdreqPG5hbzkmawbcXLKN/mf6DZW0SdNNkZ+sjwsqVkI4A4Ko2sPZmkZtCKY58w83A== + dependencies: + "@peculiar/asn1-schema" "^2.3.13" + "@peculiar/json-schema" "^1.1.12" + asn1js "^3.0.5" + pvtsutils "^1.3.5" + tslib "^2.7.0" + +webcrypto-shim@^0.1.4: + version "0.1.7" + resolved "https://registry.npmmirror.com/webcrypto-shim/-/webcrypto-shim-0.1.7.tgz#da8be23061a0451cf23b424d4a9b61c10f091c12" + integrity sha512-JAvAQR5mRNRxZW2jKigWMjCMkjSdmP5cColRP1U/pTg69VgHXEi1orv5vVpJ55Zc5MIaPc1aaurzd9pjv2bveg== + webidl-conversions@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871" @@ -6919,6 +7772,11 @@ whatwg-encoding@^1.0.5: dependencies: iconv-lite "0.4.24" +whatwg-fetch@^3.4.1: + version "3.6.20" + resolved "https://registry.npmmirror.com/whatwg-fetch/-/whatwg-fetch-3.6.20.tgz#580ce6d791facec91d37c72890995a0b48d31c70" + integrity sha512-EqhiFU6daOA8kpjOWTL0olhVOF3i7OrFzSYiGsEMB8GcXS+RrzauAERX65xMeNWVqxA6HXH2m69Z9LaKKdisfg== + whatwg-mimetype@^2.3.0: version "2.3.0" resolved "https://registry.yarnpkg.com/whatwg-mimetype/-/whatwg-mimetype-2.3.0.tgz#3d4b1e0312d2079879f826aff18dbeeca5960fbf" @@ -7089,11 +7947,16 @@ ws@8.17.1: resolved "https://registry.yarnpkg.com/ws/-/ws-8.17.1.tgz#9293da530bb548febc95371d90f9c878727d919b" integrity sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ== -ws@^7.4.6: +ws@^7.4.6, ws@^7.5.10: version "7.5.10" resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.10.tgz#58b5c20dc281633f6c19113f39b349bd8bd558d9" integrity sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ== +ws@^8.5.0: + version "8.18.0" + resolved "https://registry.npmmirror.com/ws/-/ws-8.18.0.tgz#0d7505a6eafe2b0e712d232b42279f53bc289bbc" + integrity sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw== + xml-name-validator@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/xml-name-validator/-/xml-name-validator-3.0.0.tgz#6ae73e06de4d8c6e47f9fb181f78d648ad457c6a"