From f5cd16953b5935be1a472f52b0e31aeb84dc7495 Mon Sep 17 00:00:00 2001 From: Halil Beycan <50718965+BeycanDeveloper@users.noreply.github.com> Date: Sat, 4 May 2024 11:06:27 +0800 Subject: [PATCH 01/90] added vitest ui --- package.json | 2 + packages/networks/boilerplate/package.json | 1 + packages/networks/evm-chains/package.json | 1 + packages/networks/tron/package.json | 1 + packages/utils/package.json | 1 + pnpm-lock.yaml | 61 ++++++++++++++++++++-- 6 files changed, 64 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index 22035f9..47d94e0 100644 --- a/package.json +++ b/package.json @@ -4,6 +4,7 @@ "type": "module", "scripts": { "test": "vitest", + "test-ui": "vitest watch --ui", "coverage": "vitest run --coverage", "format": "prettier --write packages/", "lint": "eslint . --ext .ts --ignore-path .gitignore" @@ -12,6 +13,7 @@ "@types/node": "^20.11.20", "@typescript-eslint/eslint-plugin": "^6.21.0", "@vitest/coverage-istanbul": "^1.5.3", + "@vitest/ui": "^1.6.0", "esbuild": "^0.20.2", "eslint": "^8.57.0", "eslint-config-prettier": "^9.1.0", diff --git a/packages/networks/boilerplate/package.json b/packages/networks/boilerplate/package.json index 54286a7..1afce77 100644 --- a/packages/networks/boilerplate/package.json +++ b/packages/networks/boilerplate/package.json @@ -41,6 +41,7 @@ "typecheck": "tsc --noEmit", "lint": "eslint . --ext .ts", "test": "vitest run --dir tests", + "test-ui": "vitest watch --ui", "prepublishOnly": "pnpm run build", "build": "pnpm run build:vite && pnpm run build:node" }, diff --git a/packages/networks/evm-chains/package.json b/packages/networks/evm-chains/package.json index f1ea16e..157848e 100644 --- a/packages/networks/evm-chains/package.json +++ b/packages/networks/evm-chains/package.json @@ -41,6 +41,7 @@ "typecheck": "tsc --noEmit", "lint": "eslint . --ext .ts", "test": "vitest run --dir tests", + "test-ui": "vitest watch --ui", "prepublishOnly": "pnpm run build", "build": "pnpm run build:vite && pnpm run build:node && tsx cdt.ts" }, diff --git a/packages/networks/tron/package.json b/packages/networks/tron/package.json index c069536..0a1b294 100644 --- a/packages/networks/tron/package.json +++ b/packages/networks/tron/package.json @@ -41,6 +41,7 @@ "typecheck": "tsc --noEmit", "lint": "eslint . --ext .ts", "test": "vitest run --dir tests", + "test-ui": "vitest watch --ui", "prepublishOnly": "pnpm run build", "build": "pnpm run build:vite && pnpm run build:node" }, diff --git a/packages/utils/package.json b/packages/utils/package.json index c04c0b8..73416fc 100644 --- a/packages/utils/package.json +++ b/packages/utils/package.json @@ -11,6 +11,7 @@ ], "scripts": { "lint": "eslint . --ext .ts", + "test-ui": "vitest watch --ui", "test": "vitest run --dir tests" }, "keywords": [ diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index ccc1e0c..a0c9747 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -14,6 +14,9 @@ devDependencies: '@vitest/coverage-istanbul': specifier: ^1.5.3 version: 1.5.3(vitest@1.3.1) + '@vitest/ui': + specifier: ^1.6.0 + version: 1.6.0(vitest@1.3.1) esbuild: specifier: ^0.20.2 version: 0.20.2 @@ -70,7 +73,7 @@ devDependencies: version: 0.21.0(vite@5.1.4) vitest: specifier: ^1.3.1 - version: 1.3.1(@types/node@20.11.20)(jsdom@24.0.0) + version: 1.3.1(@types/node@20.11.20)(@vitest/ui@1.6.0)(jsdom@24.0.0) packages: @@ -884,6 +887,10 @@ packages: engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0} dev: true + /@polka/url@1.0.0-next.25: + resolution: {integrity: sha512-j7P6Rgr3mmtdkeDGTe0E/aYyWEWVtc5yFXtHCRHs28/jptDEWfaVOc5T7cblqy1XKPPfCxJc/8DwQ5YgLOZOVQ==} + dev: true + /@rollup/plugin-inject@5.0.5: resolution: {integrity: sha512-2+DEJbNBoPROPkgTDNe8/1YXWcqxbN5DTjASVIOx8HS+pITXushyNiBV56RB08zuptzz8gT3YfkqriTBVycepg==} engines: {node: '>=14.0.0'} @@ -1244,7 +1251,7 @@ packages: magicast: 0.3.4 picocolors: 1.0.0 test-exclude: 6.0.0 - vitest: 1.3.1(@types/node@20.11.20)(jsdom@24.0.0) + vitest: 1.3.1(@types/node@20.11.20)(@vitest/ui@1.6.0)(jsdom@24.0.0) transitivePeerDependencies: - supports-color dev: true @@ -1279,6 +1286,21 @@ packages: tinyspy: 2.2.1 dev: true + /@vitest/ui@1.6.0(vitest@1.3.1): + resolution: {integrity: sha512-k3Lyo+ONLOgylctiGovRKy7V4+dIN2yxstX3eY5cWFXH6WP+ooVX79YSyi0GagdTQzLmT43BF27T0s6dOIPBXA==} + peerDependencies: + vitest: 1.6.0 + dependencies: + '@vitest/utils': 1.6.0 + fast-glob: 3.3.2 + fflate: 0.8.2 + flatted: 3.3.1 + pathe: 1.1.2 + picocolors: 1.0.0 + sirv: 2.0.4 + vitest: 1.3.1(@types/node@20.11.20)(@vitest/ui@1.6.0)(jsdom@24.0.0) + dev: true + /@vitest/utils@1.3.1: resolution: {integrity: sha512-d3Waie/299qqRyHTm2DjADeTaNdNSVsnwHPWrs20JMpjh6eiVq7ggggweO8rc4arhf6rRkWuHKwvxGvejUXZZQ==} dependencies: @@ -1288,6 +1310,15 @@ packages: pretty-format: 29.7.0 dev: true + /@vitest/utils@1.6.0: + resolution: {integrity: sha512-21cPiuGMoMZwiOHa2i4LXkMkMkCGzA+MVFV70jRwHo95dL4x/ts5GZhML1QWuy7yfp3WzK3lRvZi3JnXTYqrBw==} + dependencies: + diff-sequences: 29.6.3 + estree-walker: 3.0.3 + loupe: 2.3.7 + pretty-format: 29.7.0 + dev: true + /@volar/language-core@1.11.1: resolution: {integrity: sha512-dOcNn3i9GgZAcJt43wuaEykSluAuOkQgzni1cuxLxTV0nJKanQztp7FxyswdRILaKH+P2XZMPRp2S4MV/pElCw==} dependencies: @@ -2547,6 +2578,10 @@ packages: reusify: 1.0.4 dev: true + /fflate@0.8.2: + resolution: {integrity: sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A==} + dev: true + /file-entry-cache@6.0.1: resolution: {integrity: sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==} engines: {node: ^10.12.0 || >=12.0.0} @@ -3426,6 +3461,11 @@ packages: ufo: 1.4.0 dev: true + /mrmime@2.0.0: + resolution: {integrity: sha512-eu38+hdgojoyq63s+yTpN4XMBdt5l8HhMhc4VKLO9KM5caLIBvUm4thi7fFaxyTmCKeNnXZ5pAlBwCUnhA09uw==} + engines: {node: '>=10'} + dev: true + /ms@2.1.2: resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==} dev: true @@ -4027,6 +4067,15 @@ packages: engines: {node: '>=14'} dev: true + /sirv@2.0.4: + resolution: {integrity: sha512-94Bdh3cC2PKrbgSOUqTiGPWVZeSiXfKOVZNJniWoqrWrRkB1CJzBU3NEbiTsPcYy1lDsANA/THzS+9WBiy5nfQ==} + engines: {node: '>= 10'} + dependencies: + '@polka/url': 1.0.0-next.25 + mrmime: 2.0.0 + totalist: 3.0.1 + dev: true + /slash@3.0.0: resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} engines: {node: '>=8'} @@ -4223,6 +4272,11 @@ packages: is-number: 7.0.0 dev: true + /totalist@3.0.1: + resolution: {integrity: sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==} + engines: {node: '>=6'} + dev: true + /tough-cookie@4.1.3: resolution: {integrity: sha512-aX/y5pVRkfRnfmuX+OdbSdXvPe6ieKX/G2s7e98f4poJHnqH3281gDPm/metm6E/WRamfx7WC4HUqkWHfQHprw==} engines: {node: '>=6'} @@ -4528,7 +4582,7 @@ packages: fsevents: 2.3.3 dev: true - /vitest@1.3.1(@types/node@20.11.20)(jsdom@24.0.0): + /vitest@1.3.1(@types/node@20.11.20)(@vitest/ui@1.6.0)(jsdom@24.0.0): resolution: {integrity: sha512-/1QJqXs8YbCrfv/GPQ05wAZf2eakUPLPa18vkJAKE7RXOKfVHqMZZ1WlTjiwl6Gcn65M5vpNUB6EFLnEdRdEXQ==} engines: {node: ^18.0.0 || >=20.0.0} hasBin: true @@ -4558,6 +4612,7 @@ packages: '@vitest/runner': 1.3.1 '@vitest/snapshot': 1.3.1 '@vitest/spy': 1.3.1 + '@vitest/ui': 1.6.0(vitest@1.3.1) '@vitest/utils': 1.3.1 acorn-walk: 8.3.2 chai: 4.4.1 From f62a08d731b711060a876b4a6de07f8ee2e05e0b Mon Sep 17 00:00:00 2001 From: Halil Beycan <50718965+BeycanDeveloper@users.noreply.github.com> Date: Tue, 7 May 2024 18:56:19 +0800 Subject: [PATCH 02/90] fixed wront contract instance problem --- packages/networks/tron/src/assets/Contract.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/networks/tron/src/assets/Contract.ts b/packages/networks/tron/src/assets/Contract.ts index 8bcc2ae..500dd3d 100644 --- a/packages/networks/tron/src/assets/Contract.ts +++ b/packages/networks/tron/src/assets/Contract.ts @@ -88,7 +88,7 @@ export class Contract implements ContractInterface { async setTronContract(): Promise { if (this.tronContract !== undefined) return this.tronWeb.setAddress(this.address) - this.tronContract = await this.tronWeb.contract(this.ABI).at(this.address) + this.tronContract = await this.tronWeb.contract(this.ABI, this.address) } /** From 6f54140e8083de2d452b2d7ec5e32650ef7de2ba Mon Sep 17 00:00:00 2001 From: Halil Beycan <50718965+BeycanDeveloper@users.noreply.github.com> Date: Wed, 8 May 2024 17:24:04 +0800 Subject: [PATCH 03/90] removed isWebview condition --- packages/networks/boilerplate/index.html | 13 +------------ packages/networks/evm-chains/index.html | 13 +------------ packages/networks/tron/index.html | 13 +------------ 3 files changed, 3 insertions(+), 36 deletions(-) diff --git a/packages/networks/boilerplate/index.html b/packages/networks/boilerplate/index.html index 236da6d..4c31e53 100644 --- a/packages/networks/boilerplate/index.html +++ b/packages/networks/boilerplate/index.html @@ -215,7 +215,7 @@ + + \ No newline at end of file diff --git a/packages/networks/bitcoin/package.json b/packages/networks/bitcoin/package.json new file mode 100644 index 0000000..dc08308 --- /dev/null +++ b/packages/networks/bitcoin/package.json @@ -0,0 +1,68 @@ +{ + "name": "@multiplechain/bitcoin", + "version": "0.1.0", + "type": "module", + "main": "dist/index.cjs", + "module": "dist/index.es.js", + "unpkg": "dist/index.umd.js", + "browser": "dist/index.umd.js", + "jsdelivr": "dist/index.umd.js", + "exports": { + ".": { + "import": { + "default": "./dist/index.es.js", + "types": "./dist/browser/index.d.ts" + }, + "require": { + "default": "./dist/index.cjs", + "types": "./dist/index.d.ts" + } + }, + "./node": { + "default": "./dist/index.cjs", + "types": "./dist/index.d.ts" + }, + "./browser": { + "default": "./dist/index.es.js", + "types": "./dist/browser/index.d.ts" + } + }, + "files": [ + "dist", + "README.md", + "!tsconfig.tsbuildinfo" + ], + "scripts": { + "dev": "vite", + "clean": "rm -rf dist", + "watch": "tsc --watch", + "build:vite": "vite build", + "build:node": "tsx esbuild.ts", + "typecheck": "tsc --noEmit", + "lint": "eslint . --ext .ts", + "test": "vitest run --dir tests", + "test-ui": "vitest watch --ui", + "prepublishOnly": "pnpm run build", + "build": "pnpm run build:vite && pnpm run build:node" + }, + "keywords": [ + "web3", + "crypto", + "blockchain", + "multiple-chain" + ], + "author": "MultipleChain", + "license": "MIT", + "homepage": "https://github.com/MultipleChain/js/tree/master/packages/networks/network-name", + "repository": { + "type": "git", + "url": "git+https://github.com/MultipleChain/js.git" + }, + "bugs": { + "url": "https://github.com/MultipleChain/js/issues" + }, + "dependencies": { + "@multiplechain/types": "^0.1.55", + "@multiplechain/utils": "^0.1.18" + } +} \ No newline at end of file diff --git a/packages/networks/bitcoin/pnpm-lock.yaml b/packages/networks/bitcoin/pnpm-lock.yaml new file mode 100644 index 0000000..aae81e5 --- /dev/null +++ b/packages/networks/bitcoin/pnpm-lock.yaml @@ -0,0 +1,310 @@ +lockfileVersion: '6.0' + +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false + +dependencies: + '@multiplechain/types': + specifier: ^0.1.55 + version: 0.1.55 + '@multiplechain/utils': + specifier: ^0.1.18 + version: 0.1.18 + +packages: + + /@multiplechain/types@0.1.55: + resolution: {integrity: sha512-9fYrLaDxX2pj9zfIbmvk1hPF3FH/bK+Q3uTF+k3zdsitP/HzQ1S9zImNz20Tvoqkk1ns+/8ecE0Y6GNowsDOQA==} + dev: false + + /@multiplechain/utils@0.1.18: + resolution: {integrity: sha512-UCoOOBJrawp/lInepxuoEiYwId0wMPg7rX8p78FLqzGl8f/b93sAtv7sP87/VVKwhdoEuNZ/uQjckycmNeks/w==} + dependencies: + '@types/ws': 8.5.10 + bignumber.js: 9.1.2 + web3-utils: 4.2.1 + ws: 8.16.0 + transitivePeerDependencies: + - bufferutil + - utf-8-validate + dev: false + + /@noble/curves@1.3.0: + resolution: {integrity: sha512-t01iSXPuN+Eqzb4eBX0S5oubSqXbK/xXa1Ne18Hj8f9pStxztHCE2gfboSp/dZRLSqfuLpRK2nDXDK+W9puocA==} + dependencies: + '@noble/hashes': 1.3.3 + dev: false + + /@noble/hashes@1.3.3: + resolution: {integrity: sha512-V7/fPHgl+jsVPXqqeOzT8egNj2iBIVt+ECeMMG8TdcnTikP3oaBtUVqpT/gYCR68aEBJSF+XbYUxStjbFMqIIA==} + engines: {node: '>= 16'} + dev: false + + /@scure/base@1.1.6: + resolution: {integrity: sha512-ok9AWwhcgYuGG3Zfhyqg+zwl+Wn5uE+dwC0NV/2qQkx4dABbb/bx96vWu8NSj+BNjjSjno+JRYRjle1jV08k3g==} + dev: false + + /@scure/bip32@1.3.3: + resolution: {integrity: sha512-LJaN3HwRbfQK0X1xFSi0Q9amqOgzQnnDngIt+ZlsBC3Bm7/nE7K0kwshZHyaru79yIVRv/e1mQAjZyuZG6jOFQ==} + dependencies: + '@noble/curves': 1.3.0 + '@noble/hashes': 1.3.3 + '@scure/base': 1.1.6 + dev: false + + /@scure/bip39@1.2.2: + resolution: {integrity: sha512-HYf9TUXG80beW+hGAt3TRM8wU6pQoYur9iNypTROm42dorCGmLnFe3eWjz3gOq6G62H2WRh0FCzAR1PI+29zIA==} + dependencies: + '@noble/hashes': 1.3.3 + '@scure/base': 1.1.6 + dev: false + + /@types/node@20.12.7: + resolution: {integrity: sha512-wq0cICSkRLVaf3UGLMGItu/PtdY7oaXaI/RVU+xliKVOtRna3PRY57ZDfztpDL0n11vfymMUnXv8QwYCO7L1wg==} + dependencies: + undici-types: 5.26.5 + dev: false + + /@types/ws@8.5.10: + resolution: {integrity: sha512-vmQSUcfalpIq0R9q7uTo2lXs6eGIpt9wtnLdMv9LVpIjCA/+ufZRozlVoVelIYixx1ugCBKDhn89vnsEGOCx9A==} + dependencies: + '@types/node': 20.12.7 + dev: false + + /available-typed-arrays@1.0.7: + resolution: {integrity: sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==} + engines: {node: '>= 0.4'} + dependencies: + possible-typed-array-names: 1.0.0 + dev: false + + /bignumber.js@9.1.2: + resolution: {integrity: sha512-2/mKyZH9K85bzOEfhXDBFZTGd1CTs+5IHpeFQo9luiBG7hghdC851Pj2WAhb6E3R6b9tZj/XKhbg4fum+Kepug==} + dev: false + + /call-bind@1.0.7: + resolution: {integrity: sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==} + engines: {node: '>= 0.4'} + dependencies: + es-define-property: 1.0.0 + es-errors: 1.3.0 + function-bind: 1.1.2 + get-intrinsic: 1.2.4 + set-function-length: 1.2.2 + dev: false + + /define-data-property@1.1.4: + resolution: {integrity: sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==} + engines: {node: '>= 0.4'} + dependencies: + es-define-property: 1.0.0 + es-errors: 1.3.0 + gopd: 1.0.1 + dev: false + + /es-define-property@1.0.0: + resolution: {integrity: sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==} + engines: {node: '>= 0.4'} + dependencies: + get-intrinsic: 1.2.4 + dev: false + + /es-errors@1.3.0: + resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==} + engines: {node: '>= 0.4'} + dev: false + + /ethereum-cryptography@2.1.3: + resolution: {integrity: sha512-BlwbIL7/P45W8FGW2r7LGuvoEZ+7PWsniMvQ4p5s2xCyw9tmaDlpfsN9HjAucbF+t/qpVHwZUisgfK24TCW8aA==} + dependencies: + '@noble/curves': 1.3.0 + '@noble/hashes': 1.3.3 + '@scure/bip32': 1.3.3 + '@scure/bip39': 1.2.2 + dev: false + + /eventemitter3@5.0.1: + resolution: {integrity: sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==} + dev: false + + /for-each@0.3.3: + resolution: {integrity: sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==} + dependencies: + is-callable: 1.2.7 + dev: false + + /function-bind@1.1.2: + resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} + dev: false + + /get-intrinsic@1.2.4: + resolution: {integrity: sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==} + engines: {node: '>= 0.4'} + dependencies: + es-errors: 1.3.0 + function-bind: 1.1.2 + has-proto: 1.0.3 + has-symbols: 1.0.3 + hasown: 2.0.2 + dev: false + + /gopd@1.0.1: + resolution: {integrity: sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==} + dependencies: + get-intrinsic: 1.2.4 + dev: false + + /has-property-descriptors@1.0.2: + resolution: {integrity: sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==} + dependencies: + es-define-property: 1.0.0 + dev: false + + /has-proto@1.0.3: + resolution: {integrity: sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==} + engines: {node: '>= 0.4'} + dev: false + + /has-symbols@1.0.3: + resolution: {integrity: sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==} + engines: {node: '>= 0.4'} + dev: false + + /has-tostringtag@1.0.2: + resolution: {integrity: sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==} + engines: {node: '>= 0.4'} + dependencies: + has-symbols: 1.0.3 + dev: false + + /hasown@2.0.2: + resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} + engines: {node: '>= 0.4'} + dependencies: + function-bind: 1.1.2 + dev: false + + /inherits@2.0.4: + resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} + dev: false + + /is-arguments@1.1.1: + resolution: {integrity: sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.7 + has-tostringtag: 1.0.2 + dev: false + + /is-callable@1.2.7: + resolution: {integrity: sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==} + engines: {node: '>= 0.4'} + dev: false + + /is-generator-function@1.0.10: + resolution: {integrity: sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==} + engines: {node: '>= 0.4'} + dependencies: + has-tostringtag: 1.0.2 + dev: false + + /is-typed-array@1.1.13: + resolution: {integrity: sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw==} + engines: {node: '>= 0.4'} + dependencies: + which-typed-array: 1.1.15 + dev: false + + /possible-typed-array-names@1.0.0: + resolution: {integrity: sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==} + engines: {node: '>= 0.4'} + dev: false + + /set-function-length@1.2.2: + resolution: {integrity: sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==} + engines: {node: '>= 0.4'} + dependencies: + define-data-property: 1.1.4 + es-errors: 1.3.0 + function-bind: 1.1.2 + get-intrinsic: 1.2.4 + gopd: 1.0.1 + has-property-descriptors: 1.0.2 + dev: false + + /undici-types@5.26.5: + resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==} + dev: false + + /util@0.12.5: + resolution: {integrity: sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA==} + dependencies: + inherits: 2.0.4 + is-arguments: 1.1.1 + is-generator-function: 1.0.10 + is-typed-array: 1.1.13 + which-typed-array: 1.1.15 + dev: false + + /web3-errors@1.1.4: + resolution: {integrity: sha512-WahtszSqILez+83AxGecVroyZsMuuRT+KmQp4Si5P4Rnqbczno1k748PCrZTS1J4UCPmXMG2/Vt+0Bz2zwXkwQ==} + engines: {node: '>=14', npm: '>=6.12.0'} + dependencies: + web3-types: 1.5.0 + dev: false + + /web3-types@1.5.0: + resolution: {integrity: sha512-geWuMIeegQ8AedKAO6wO4G4j1gyQ1F/AyKLMw2vud4bsfZayyzWJgCMDZtjYMm5uo2a7i8j1W3/4QFmzlSy5cw==} + engines: {node: '>=14', npm: '>=6.12.0'} + dev: false + + /web3-utils@4.2.1: + resolution: {integrity: sha512-Fk29BlEqD9Q9Cnw4pBkKw7czcXiRpsSco/BzEUl4ye0ZTSHANQFfjsfQmNm4t7uY11u6Ah+8F3tNjBeU4CA80A==} + engines: {node: '>=14', npm: '>=6.12.0'} + dependencies: + ethereum-cryptography: 2.1.3 + eventemitter3: 5.0.1 + web3-errors: 1.1.4 + web3-types: 1.5.0 + web3-validator: 2.0.4 + dev: false + + /web3-validator@2.0.4: + resolution: {integrity: sha512-qRxVePwdW+SByOmTpDZFWHIUAa7PswvxNszrOua6BoGqAhERo5oJZBN+EbWtK/+O+ApNxt5FR3nCPmiZldiOQA==} + engines: {node: '>=14', npm: '>=6.12.0'} + dependencies: + ethereum-cryptography: 2.1.3 + util: 0.12.5 + web3-errors: 1.1.4 + web3-types: 1.5.0 + zod: 3.22.4 + dev: false + + /which-typed-array@1.1.15: + resolution: {integrity: sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA==} + engines: {node: '>= 0.4'} + dependencies: + available-typed-arrays: 1.0.7 + call-bind: 1.0.7 + for-each: 0.3.3 + gopd: 1.0.1 + has-tostringtag: 1.0.2 + dev: false + + /ws@8.16.0: + resolution: {integrity: sha512-HS0c//TP7Ina87TfiPUz1rQzMhHrl/SG2guqRcTOIUYD2q8uhUdNHZYJUaQ8aTGPzCh+c6oawMKW35nFl1dxyQ==} + engines: {node: '>=10.0.0'} + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: '>=5.0.2' + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + dev: false + + /zod@3.22.4: + resolution: {integrity: sha512-iC+8Io04lddc+mVqQ9AZ7OQ2MrUKGN+oIQyq1vemgt46jwCwLfhq7/pwnBnNXXXZb8VTVLKwp9EDkx+ryxIWmg==} + dev: false diff --git a/packages/networks/bitcoin/src/assets/Coin.ts b/packages/networks/bitcoin/src/assets/Coin.ts new file mode 100644 index 0000000..1c2d8b3 --- /dev/null +++ b/packages/networks/bitcoin/src/assets/Coin.ts @@ -0,0 +1,60 @@ +import { Provider } from '../services/Provider.ts' +import type { CoinInterface } from '@multiplechain/types' +import { CoinTransactionSigner } from '../services/TransactionSigner.ts' + +export class Coin implements CoinInterface { + /** + * Blockchain network provider + */ + provider: Provider + + /** + * @param {Provider} provider network provider + */ + constructor(provider?: Provider) { + this.provider = provider ?? Provider.instance + } + + /** + * @returns {string} Coin name + */ + getName(): string { + return 'example' + } + + /** + * @returns {string} Coin symbol + */ + getSymbol(): string { + return 'example' + } + + /** + * @returns {number} Decimal value of the coin + */ + getDecimals(): number { + return 18 + } + + /** + * @param {string} owner Wallet address + * @returns {Promise} Wallet balance as currency of COIN + */ + async getBalance(owner: string): Promise { + return 0 + } + + /** + * @param {string} sender Sender wallet address + * @param {string} receiver Receiver wallet address + * @param {number} amount Amount of assets that will be transferred + * @returns {Promise} Transaction signer + */ + async transfer( + sender: string, + receiver: string, + amount: number + ): Promise { + return new CoinTransactionSigner('example') + } +} diff --git a/packages/networks/bitcoin/src/assets/Contract.ts b/packages/networks/bitcoin/src/assets/Contract.ts new file mode 100644 index 0000000..ee3a295 --- /dev/null +++ b/packages/networks/bitcoin/src/assets/Contract.ts @@ -0,0 +1,58 @@ +import { Provider } from '../services/Provider.ts' +import type { ContractInterface } from '@multiplechain/types' + +export class Contract implements ContractInterface { + /** + * Contract address + */ + address: string + + /** + * Blockchain network provider + */ + provider: Provider + + /** + * @param {string} address Contract address + * @param {Provider} provider Blockchain network provider + */ + constructor(address: string, provider?: Provider) { + this.address = address + this.provider = provider ?? Provider.instance + } + + /** + * @returns {string} Contract address + */ + getAddress(): string { + return this.address + } + + /** + * @param {string} method Method name + * @param {any[]} args Method parameters + * @returns {Promise} Method result + */ + async callMethod(method: string, ...args: any[]): Promise { + return {} + } + + /** + * @param {string} method Method name + * @param {any[]} args Sender wallet address + * @returns {Promise} Encoded method data + */ + async getMethodData(method: string, ...args: any[]): Promise { + return {} + } + + /** + * @param {string} method Method name + * @param {string} from Sender wallet address + * @param {any[]} args Method parameters + * @returns {Promise} Encoded method data + */ + async createTransactionData(method: string, from: string, ...args: any[]): Promise { + return '' + } +} diff --git a/packages/networks/bitcoin/src/assets/NFT.ts b/packages/networks/bitcoin/src/assets/NFT.ts new file mode 100644 index 0000000..0a89a51 --- /dev/null +++ b/packages/networks/bitcoin/src/assets/NFT.ts @@ -0,0 +1,96 @@ +import { Contract } from './Contract.ts' +import type { NftInterface } from '@multiplechain/types' +import { NftTransactionSigner } from '../services/TransactionSigner.ts' + +export class NFT extends Contract implements NftInterface { + /** + * @returns {Promise} NFT name + */ + async getName(): Promise { + return 'example' + } + + /** + * @returns {Promise} NFT symbol + */ + async getSymbol(): Promise { + return 'example' + } + + /** + * @param {string} owner Wallet address + * @returns {Promise} Wallet balance as currency of NFT + */ + async getBalance(owner: string): Promise { + return 0 + } + + /** + * @param {number | string} nftId NFT ID + * @returns {Promise} Wallet address of the owner of the NFT + */ + async getOwner(nftId: number | string): Promise { + return 'example' + } + + /** + * @param {number | string} nftId NFT ID + * @returns {Promise} URI of the NFT + */ + async getTokenURI(nftId: number | string): Promise { + return 'example' + } + + /** + * @param {number | string} nftId ID of the NFT that will be transferred + * @returns {Promise} Wallet address of the approved spender + */ + async getApproved(nftId: number | string): Promise { + return 'example' + } + + /** + * @param {string} sender Sender address + * @param {string} receiver Receiver address + * @param {number | string} nftId NFT ID + * @returns {Promise} Transaction signer + */ + async transfer( + sender: string, + receiver: string, + nftId: number | string + ): Promise { + return new NftTransactionSigner('example') + } + + /** + * @param {string} spender Spender address + * @param {string} owner Owner address + * @param {string} receiver Receiver address + * @param {number | string} nftId NFT ID + * @returns {Promise} Transaction signer + */ + async transferFrom( + spender: string, + owner: string, + receiver: string, + nftId: number | string + ): Promise { + return new NftTransactionSigner('example') + } + + /** + * Gives permission to the spender to spend owner's tokens + * @param {string} owner Address of owner of the tokens that will be used + * @param {string} spender Address of the spender that will use the tokens of owner + * @param {number | string} nftId ID of the NFT that will be transferred + * @returns {Promise} Transaction signer + */ + async approve( + owner: string, + spender: string, + nftId: number | string + ): Promise { + return new NftTransactionSigner('example') + } +} diff --git a/packages/networks/bitcoin/src/assets/Token.ts b/packages/networks/bitcoin/src/assets/Token.ts new file mode 100644 index 0000000..8d30a0d --- /dev/null +++ b/packages/networks/bitcoin/src/assets/Token.ts @@ -0,0 +1,96 @@ +import { Contract } from './Contract.ts' +import type { TokenInterface } from '@multiplechain/types' +import { TokenTransactionSigner } from '../services/TransactionSigner.ts' + +export class Token extends Contract implements TokenInterface { + /** + * @returns {Promise} Token name + */ + async getName(): Promise { + return 'example' + } + + /** + * @returns {Promise} Token symbol + */ + async getSymbol(): Promise { + return 'example' + } + + /** + * @returns {Promise} Decimal value of the token + */ + async getDecimals(): Promise { + return 18 + } + + /** + * @param {string} owner Wallet address + * @returns {Promise} Wallet balance as currency of TOKEN + */ + async getBalance(owner: string): Promise { + return 0 + } + + /** + * @returns {Promise} Total supply of the token + */ + async getTotalSupply(): Promise { + return 0 + } + + /** + * @param {string} owner Address of owner of the tokens that is being used + * @param {string} spender Address of the spender that is using the tokens of owner + * @returns {Promise} Amount of tokens that the spender is allowed to spend + */ + async getAllowance(owner: string, spender: string): Promise { + return 0 + } + + /** + * transfer() method is the main method for processing transfers for fungible assets (TOKEN, COIN) + * @param {string} sender Sender wallet address + * @param {string} receiver Receiver wallet address + * @param {number} amount Amount of assets that will be transferred + * @returns {Promise} Transaction signer + */ + async transfer( + sender: string, + receiver: string, + amount: number + ): Promise { + return new TokenTransactionSigner('example') + } + + /** + * @param {string} spender Address of the spender of transaction + * @param {string} owner Sender wallet address + * @param {string} receiver Receiver wallet address + * @param {number} amount Amount of tokens that will be transferred + * @returns {Promise} Transaction signer + */ + async transferFrom( + spender: string, + owner: string, + receiver: string, + amount: number + ): Promise { + return new TokenTransactionSigner('example') + } + + /** + * Gives permission to the spender to spend owner's tokens + * @param {string} owner Address of owner of the tokens that will be used + * @param {string} spender Address of the spender that will use the tokens of owner + * @param {number} amount Amount of the tokens that will be used + * @returns {Promise} Transaction signer + */ + async approve( + owner: string, + spender: string, + amount: number + ): Promise { + return new TokenTransactionSigner('example') + } +} diff --git a/packages/networks/bitcoin/src/assets/index.ts b/packages/networks/bitcoin/src/assets/index.ts new file mode 100644 index 0000000..7ea522f --- /dev/null +++ b/packages/networks/bitcoin/src/assets/index.ts @@ -0,0 +1,4 @@ +export * from './NFT.ts' +export * from './Coin.ts' +export * from './Token.ts' +export * from './Contract.ts' diff --git a/packages/networks/bitcoin/src/browser/Wallet.ts b/packages/networks/bitcoin/src/browser/Wallet.ts new file mode 100644 index 0000000..652d8a1 --- /dev/null +++ b/packages/networks/bitcoin/src/browser/Wallet.ts @@ -0,0 +1,128 @@ +import type { + WalletInterface, + WalletAdapterInterface, + WalletPlatformEnum, + TransactionSignerInterface, + ProviderInterface +} from '@multiplechain/types' +import { Provider } from '../services/Provider' + +export class Wallet implements WalletInterface { + adapter: WalletAdapterInterface + + walletProvider: object + + networkProvider: Provider + + /** + * @param {WalletAdapterInterface} adapter + * @param {Provider} provider + */ + constructor(adapter: WalletAdapterInterface, provider?: Provider) { + this.adapter = adapter + this.networkProvider = provider ?? Provider.instance + } + + /** + * @returns {string} + */ + getId(): string { + return this.adapter.id + } + + /** + * @returns {string} + */ + getName(): string { + return this.adapter.name + } + + /** + * @returns {string} + */ + getIcon(): string { + return this.adapter.icon + } + + /** + * @returns {WalletPlatformEnum[]} + */ + getPlatforms(): WalletPlatformEnum[] { + return this.adapter.platforms + } + + /** + * @returns {string} + */ + getDownloadLink(): string | undefined { + return this.adapter.downloadLink + } + + /** + * @param {string} url + * @param {object} ops + * @returns {string} + */ + createDeepLink(url: string, ops?: object): string | null { + if (this.adapter.createDeepLink === undefined) { + return null + } + + return this.adapter.createDeepLink(url, ops) + } + + /** + * @param {ProviderInterface} provider + * @param {Object} ops + * @returns {Promise} + */ + async connect(provider?: ProviderInterface, ops?: object): Promise { + await this.adapter.connect() + return 'wallet address' + } + + /** + * @returns {boolean} + */ + async isDetected(): Promise { + return await this.adapter.isDetected() + } + + /** + * @returns {boolean} + */ + async isConnected(): Promise { + return await this.adapter.isConnected() + } + + /** + * @returns {Promise} + */ + async getAddress(): Promise { + return 'wallet address' + } + + /** + * @param {string} message + */ + async signMessage(message: string): Promise { + return 'signed message' + } + + /** + * @param {TransactionSignerInterface} transactionSigner + * @returns {Promise} + */ + async sendTransaction(transactionSigner: TransactionSignerInterface): Promise { + return 'transaction hash' + } + + /** + * @param {string} eventName + * @param {Function} callback + * @returns {void} + */ + on(eventName: string, callback: (...args: any[]) => void): void { + 'wallet events' + } +} diff --git a/packages/networks/bitcoin/src/browser/adapters/Example.ts b/packages/networks/bitcoin/src/browser/adapters/Example.ts new file mode 100644 index 0000000..79ecd67 --- /dev/null +++ b/packages/networks/bitcoin/src/browser/adapters/Example.ts @@ -0,0 +1,29 @@ +import { WalletPlatformEnum } from '@multiplechain/types' +import type { WalletAdapterInterface } from '@multiplechain/types' + +declare global { + interface Window { + example: any + } +} + +const Example: WalletAdapterInterface = { + id: 'example', + name: 'Example', + icon: 'icon base64 string here', + platforms: [WalletPlatformEnum.BROWSER, WalletPlatformEnum.MOBILE], + downloadLink: 'wallet download link here', + createDeepLink(url: string, ops?: object): string { + return `https://example.com/dapp/${url}` + }, + isDetected: () => Boolean(window?.example), + isConnected: async () => { + return true // return true if connected + }, + connect: async () => { + // connect wallet here + return window.example + } +} + +export default Example diff --git a/packages/networks/bitcoin/src/browser/adapters/index.ts b/packages/networks/bitcoin/src/browser/adapters/index.ts new file mode 100644 index 0000000..de0149d --- /dev/null +++ b/packages/networks/bitcoin/src/browser/adapters/index.ts @@ -0,0 +1 @@ +export { default as Example } from './Example.ts' diff --git a/packages/networks/bitcoin/src/browser/index.ts b/packages/networks/bitcoin/src/browser/index.ts new file mode 100644 index 0000000..787e9bd --- /dev/null +++ b/packages/networks/bitcoin/src/browser/index.ts @@ -0,0 +1,25 @@ +import { Wallet } from './Wallet.ts' +import * as adapterList from './adapters/index.ts' +import type { + WalletAdapterListType, + WalletAdapterInterface, + RegisterWalletAdapterType +} from '@multiplechain/types' + +const adapters: WalletAdapterListType = {} + +const registerAdapter: RegisterWalletAdapterType = (adapter: WalletAdapterInterface): void => { + if (Object.values(adapters).find((a) => a.id === adapter.id) !== undefined) { + throw new Error(`Adapter with id ${adapter.id} already exists`) + } + + adapters[adapter.id] = adapter +} + +export * from '../index.ts' + +export const browser = { + Wallet, + registerAdapter, + adapters: Object.assign(adapters, adapterList) +} diff --git a/packages/networks/bitcoin/src/index.ts b/packages/networks/bitcoin/src/index.ts new file mode 100644 index 0000000..668ab52 --- /dev/null +++ b/packages/networks/bitcoin/src/index.ts @@ -0,0 +1,8 @@ +export * from './services/Provider.ts' + +export * as assets from './assets/index.ts' +export * as models from './models/index.ts' +export * as services from './services/index.ts' + +export * as utils from '@multiplechain/utils' +export * as types from '@multiplechain/types' diff --git a/packages/networks/bitcoin/src/models/CoinTransaction.ts b/packages/networks/bitcoin/src/models/CoinTransaction.ts new file mode 100644 index 0000000..9857f2e --- /dev/null +++ b/packages/networks/bitcoin/src/models/CoinTransaction.ts @@ -0,0 +1,40 @@ +import { Transaction } from './Transaction.ts' +import { TransactionStatusEnum } from '@multiplechain/types' +import type { AssetDirectionEnum, CoinTransactionInterface } from '@multiplechain/types' + +export class CoinTransaction extends Transaction implements CoinTransactionInterface { + /** + * @returns {Promise} Wallet address of the receiver of transaction + */ + async getReceiver(): Promise { + return 'example' + } + + /** + * @returns {Promise} Wallet address of the sender of transaction + */ + async getSender(): Promise { + return 'example' + } + + /** + * @returns {Promise} Amount of coin that will be transferred + */ + async getAmount(): Promise { + return 0 + } + + /** + * @param {AssetDirectionEnum} direction - Direction of the transaction (asset) + * @param {string} address - Wallet address of the receiver or sender of the transaction, dependant on direction + * @param {number} amount Amount of assets that will be transferred + * @returns {Promise} Status of the transaction + */ + async verifyTransfer( + direction: AssetDirectionEnum, + address: string, + amount: number + ): Promise { + return TransactionStatusEnum.PENDING + } +} diff --git a/packages/networks/bitcoin/src/models/ContractTransaction.ts b/packages/networks/bitcoin/src/models/ContractTransaction.ts new file mode 100644 index 0000000..ad57241 --- /dev/null +++ b/packages/networks/bitcoin/src/models/ContractTransaction.ts @@ -0,0 +1,11 @@ +import { Transaction } from './Transaction.ts' +import type { ContractTransactionInterface } from '@multiplechain/types' + +export class ContractTransaction extends Transaction implements ContractTransactionInterface { + /** + * @returns {Promise} Contract address of the transaction + */ + async getAddress(): Promise { + return 'example' + } +} diff --git a/packages/networks/bitcoin/src/models/NftTransaction.ts b/packages/networks/bitcoin/src/models/NftTransaction.ts new file mode 100644 index 0000000..09b8d80 --- /dev/null +++ b/packages/networks/bitcoin/src/models/NftTransaction.ts @@ -0,0 +1,41 @@ +import { ContractTransaction } from './ContractTransaction.ts' +import { TransactionStatusEnum } from '@multiplechain/types' +import type { NftTransactionInterface, AssetDirectionEnum } from '@multiplechain/types' + +export class NftTransaction extends ContractTransaction implements NftTransactionInterface { + /** + * @returns {Promise} Receiver wallet address + */ + async getReceiver(): Promise { + return 'example' + } + + /** + * @returns {Promise} Wallet address of the sender of transaction + */ + async getSender(): Promise { + return 'example' + } + + /** + * @returns {Promise} NFT ID + */ + async getNftId(): Promise { + return 0 + } + + /** + * @param {AssetDirectionEnum} direction - Direction of the transaction (nft) + * @param {string} address - Wallet address of the receiver or sender of the transaction, dependant on direction + * @param {number} nftId ID of the NFT that will be transferred + * @override verifyTransfer() in AssetTransactionInterface + * @returns {Promise} Status of the transaction + */ + async verifyTransfer( + direction: AssetDirectionEnum, + address: string, + nftId: number | string + ): Promise { + return TransactionStatusEnum.PENDING + } +} diff --git a/packages/networks/bitcoin/src/models/TokenTransaction.ts b/packages/networks/bitcoin/src/models/TokenTransaction.ts new file mode 100644 index 0000000..b1ea29e --- /dev/null +++ b/packages/networks/bitcoin/src/models/TokenTransaction.ts @@ -0,0 +1,40 @@ +import { ContractTransaction } from './ContractTransaction.ts' +import { TransactionStatusEnum } from '@multiplechain/types' +import type { AssetDirectionEnum, TokenTransactionInterface } from '@multiplechain/types' + +export class TokenTransaction extends ContractTransaction implements TokenTransactionInterface { + /** + * @returns {Promise} Wallet address of the receiver of transaction + */ + async getReceiver(): Promise { + return 'example' + } + + /** + * @returns {Promise} Wallet address of the sender of transaction + */ + async getSender(): Promise { + return 'example' + } + + /** + * @returns {Promise} Amount of tokens that will be transferred + */ + async getAmount(): Promise { + return 0 + } + + /** + * @param {AssetDirectionEnum} direction - Direction of the transaction (token) + * @param {string} address - Wallet address of the owner or spender of the transaction, dependant on direction + * @param {number} amount Amount of tokens that will be approved + * @returns {Promise} Status of the transaction + */ + async verifyTransfer( + direction: AssetDirectionEnum, + address: string, + amount: number + ): Promise { + return TransactionStatusEnum.PENDING + } +} diff --git a/packages/networks/bitcoin/src/models/Transaction.ts b/packages/networks/bitcoin/src/models/Transaction.ts new file mode 100644 index 0000000..15f111d --- /dev/null +++ b/packages/networks/bitcoin/src/models/Transaction.ts @@ -0,0 +1,94 @@ +import { Provider } from '../services/Provider.ts' +import type { TransactionInterface } from '@multiplechain/types' +import { TransactionStatusEnum } from '@multiplechain/types' + +export class Transaction implements TransactionInterface { + /** + * Each transaction has its own unique ID defined by the user + */ + id: string + + /** + * Blockchain network provider + */ + provider: Provider + + /** + * @param {string} id Transaction id + * @param {Provider} provider Blockchain network provider + */ + constructor(id: string, provider?: Provider) { + this.id = id + this.provider = provider ?? Provider.instance + } + + /** + * @returns {Promise} Transaction data + */ + async getData(): Promise { + return {} + } + + /** + * @returns {Promise} Wait for the transaction to be confirmed + */ + async wait(): Promise { + return await Promise.resolve(TransactionStatusEnum.CONFIRMED) + } + + /** + * @returns {string} Transaction ID + */ + getId(): string { + return this.id + } + + /** + * @returns {string} Transaction URL + */ + getUrl(): string { + return 'example' + } + + /** + * @returns {Promise} Wallet address of the sender of transaction + */ + async getSigner(): Promise { + return 'example' + } + + /** + * @returns {Promise} Transaction fee + */ + async getFee(): Promise { + return 0 + } + + /** + * @returns {Promise} Block number that transaction + */ + async getBlockNumber(): Promise { + return 0 + } + + /** + * @returns {Promise} Block timestamp that transaction + */ + async getBlockTimestamp(): Promise { + return 0 + } + + /** + * @returns {Promise} Confirmation count of the block + */ + async getBlockConfirmationCount(): Promise { + return 0 + } + + /** + * @returns {Promise} Status of the transaction + */ + async getStatus(): Promise { + return TransactionStatusEnum.CONFIRMED + } +} diff --git a/packages/networks/bitcoin/src/models/index.ts b/packages/networks/bitcoin/src/models/index.ts new file mode 100644 index 0000000..cc0a27c --- /dev/null +++ b/packages/networks/bitcoin/src/models/index.ts @@ -0,0 +1,5 @@ +export * from './Transaction.ts' +export * from './NftTransaction.ts' +export * from './CoinTransaction.ts' +export * from './TokenTransaction.ts' +export * from './ContractTransaction.ts' diff --git a/packages/networks/bitcoin/src/services/Provider.ts b/packages/networks/bitcoin/src/services/Provider.ts new file mode 100644 index 0000000..9377756 --- /dev/null +++ b/packages/networks/bitcoin/src/services/Provider.ts @@ -0,0 +1,81 @@ +import { + ErrorTypeEnum, + type NetworkConfigInterface, + type ProviderInterface +} from '@multiplechain/types' + +export class Provider implements ProviderInterface { + /** + * Network configuration of the provider + */ + network: NetworkConfigInterface + + /** + * Static instance of the provider + */ + private static _instance: Provider + + /** + * @param network - Network configuration of the provider + */ + constructor(network: NetworkConfigInterface) { + this.network = network + } + + /** + * Get the static instance of the provider + * @returns {Provider} Provider + */ + static get instance(): Provider { + if (Provider._instance === undefined) { + throw new Error(ErrorTypeEnum.PROVIDER_IS_NOT_INITIALIZED) + } + return Provider._instance + } + + /** + * Initialize the static instance of the provider + * @param {NetworkConfigInterface} network - Network configuration of the provider + * @returns {void} + */ + static initialize(network: NetworkConfigInterface): void { + if (Provider._instance !== undefined) { + throw new Error(ErrorTypeEnum.PROVIDER_IS_ALREADY_INITIALIZED) + } + Provider._instance = new Provider(network) + } + + /** + * Check RPC connection + * @param {string} url - RPC URL + * @returns {Promise} + */ + async checkRpcConnection(url?: string): Promise { + return true + } + + /** + * Check WS connection + * @param {string} url - Websocket URL + * @returns {Promise} + */ + async checkWsConnection(url?: string): Promise { + return true + } + + /** + * Update network configuration of the provider + * @param network - Network configuration of the provider + */ + update(network: NetworkConfigInterface): void { + this.network = network + } + + /** + * Get the current network configuration is testnet or not + * @returns boolean + */ + isTestnet(): boolean { + return this.network?.testnet ?? false + } +} diff --git a/packages/networks/bitcoin/src/services/TransactionListener.ts b/packages/networks/bitcoin/src/services/TransactionListener.ts new file mode 100644 index 0000000..47ee7d8 --- /dev/null +++ b/packages/networks/bitcoin/src/services/TransactionListener.ts @@ -0,0 +1,150 @@ +import type { + TransactionTypeEnum, + DynamicTransactionType, + TransactionListenerInterface, + TransactionListenerCallbackType, + DynamicTransactionListenerFilterType +} from '@multiplechain/types' + +import { Provider } from './Provider.ts' +import { TransactionListenerProcessIndex } from '@multiplechain/types' + +export class TransactionListener + implements TransactionListenerInterface +{ + /** + * Transaction type + */ + type: T + + /** + * Transaction listener callback + */ + callbacks: TransactionListenerCallbackType[] = [] + + /** + * Transaction listener filter + */ + filter?: DynamicTransactionListenerFilterType + + /** + * Provider + */ + provider: Provider + + /** + * Listener status + */ + status: boolean = false + + /** + * Triggered transactions + */ + triggeredTransactions: string[] = [] + + /** + * @param {T} type - Transaction type + * @param {DynamicTransactionListenerFilterType} filter - Transaction listener filter + * @param {Provider} provider - Provider + */ + constructor(type: T, filter?: DynamicTransactionListenerFilterType, provider?: Provider) { + this.type = type + this.filter = filter + this.provider = provider ?? Provider.instance + } + + /** + * Close the listener + * @returns {void} + */ + stop(): void { + if (this.status) { + this.status = false + // stop the listener + } + } + + /** + * Start the listener + * @returns {void} + */ + start(): void { + if (!this.status) { + this.status = true + // @ts-expect-error allow dynamic access + this[TransactionListenerProcessIndex[this.type]]() + } + } + + /** + * Get the listener status + * @returns {boolean} Listener status + */ + getStatus(): boolean { + return this.status + } + + /** + * Listen to the transaction events + * @param {TransactionListenerCallbackType} callback - Transaction listener callback + * @returns {Promise} + */ + async on(callback: TransactionListenerCallbackType): Promise { + this.callbacks.push(callback) + return true + } + + /** + * Trigger the event when a transaction is detected + * @param {DynamicTransactionType} transaction - Transaction data + * @returns {void} + */ + trigger(transaction: DynamicTransactionType): void { + if (!this.triggeredTransactions.includes(transaction.id)) { + this.triggeredTransactions.push(transaction.id) + this.callbacks.forEach((callback) => { + callback(transaction) + }) + } + } + + /** + * General transaction process + * @returns {void} + */ + generalProcess(): void { + // General transaction process + } + + /** + * Contract transaction process + * @returns {void} + */ + contractProcess(): void { + // Contract transaction process + } + + /** + * Coin transaction process + * @returns {void} + */ + coinProcess(): void { + // Coin transaction process + } + + /** + * Token transaction process + * @returns {void} + */ + tokenProcess(): void { + // Token transaction process + } + + /** + * NFT transaction process + * @returns {void} + */ + nftProcess(): void { + // NFT transaction process + } +} diff --git a/packages/networks/bitcoin/src/services/TransactionSigner.ts b/packages/networks/bitcoin/src/services/TransactionSigner.ts new file mode 100644 index 0000000..a76019e --- /dev/null +++ b/packages/networks/bitcoin/src/services/TransactionSigner.ts @@ -0,0 +1,94 @@ +import { Provider } from '../services/Provider.ts' +import { Transaction } from '../models/Transaction.ts' +import { NftTransaction } from '../models/NftTransaction.ts' +import { CoinTransaction } from '../models/CoinTransaction.ts' +import { TokenTransaction } from '../models/TokenTransaction.ts' +import type { TransactionSignerInterface } from '@multiplechain/types' + +export class TransactionSigner implements TransactionSignerInterface { + /** + * Transaction data from the blockchain network + */ + rawData: any + + /** + * Signed transaction data + */ + signedData?: any + + /** + * Blockchain network provider + */ + provider: Provider + + /** + * @param {any} rawData - Transaction data + */ + constructor(rawData: any, provider?: Provider) { + this.rawData = rawData + this.provider = provider ?? Provider.instance + } + + /** + * Sign the transaction + * @param {string} privateKey - Transaction data + * @returns {Promise} Signed transaction data + */ + async sign(privateKey: string): Promise { + return await Promise.resolve(this) + } + + /** + * Send the transaction to the blockchain network + * @returns {Promise} + */ + async send(): Promise { + return await Promise.resolve(new Transaction('example')) + } + + /** + * Get the raw transaction data + * @returns Transaction data + */ + getRawData(): any { + return this.rawData + } + + /** + * Get the signed transaction data + * @returns Signed transaction data + */ + getSignedData(): any { + return this.signedData + } +} + +export class CoinTransactionSigner extends TransactionSigner { + /** + * Send the transaction to the blockchain network + * @returns {Promise} Transaction data + */ + async send(): Promise { + return new CoinTransaction((await super.send()).getId()) + } +} + +export class TokenTransactionSigner extends TransactionSigner { + /** + * Send the transaction to the blockchain network + * @returns {Promise} Transaction data + */ + async send(): Promise { + return new TokenTransaction((await super.send()).getId()) + } +} + +export class NftTransactionSigner extends TransactionSigner { + /** + * Send the transaction to the blockchain network + * @returns {Promise} Transaction data + */ + async send(): Promise { + return new NftTransaction((await super.send()).getId()) + } +} diff --git a/packages/networks/bitcoin/src/services/index.ts b/packages/networks/bitcoin/src/services/index.ts new file mode 100644 index 0000000..549a382 --- /dev/null +++ b/packages/networks/bitcoin/src/services/index.ts @@ -0,0 +1,2 @@ +export * from './TransactionSigner.ts' +export * from './TransactionListener.ts' diff --git a/packages/networks/bitcoin/tests/assets.spec.ts b/packages/networks/bitcoin/tests/assets.spec.ts new file mode 100644 index 0000000..34c5579 --- /dev/null +++ b/packages/networks/bitcoin/tests/assets.spec.ts @@ -0,0 +1,7 @@ +import { describe, it, expect } from 'vitest' + +describe('example', () => { + it('should work', () => { + expect(1 + 1).toBe(2) + }) +}) diff --git a/packages/networks/bitcoin/tests/models.spec.ts b/packages/networks/bitcoin/tests/models.spec.ts new file mode 100644 index 0000000..34c5579 --- /dev/null +++ b/packages/networks/bitcoin/tests/models.spec.ts @@ -0,0 +1,7 @@ +import { describe, it, expect } from 'vitest' + +describe('example', () => { + it('should work', () => { + expect(1 + 1).toBe(2) + }) +}) diff --git a/packages/networks/bitcoin/tests/services.spec.ts b/packages/networks/bitcoin/tests/services.spec.ts new file mode 100644 index 0000000..34c5579 --- /dev/null +++ b/packages/networks/bitcoin/tests/services.spec.ts @@ -0,0 +1,7 @@ +import { describe, it, expect } from 'vitest' + +describe('example', () => { + it('should work', () => { + expect(1 + 1).toBe(2) + }) +}) diff --git a/packages/networks/bitcoin/tests/setup.ts b/packages/networks/bitcoin/tests/setup.ts new file mode 100644 index 0000000..e69de29 diff --git a/packages/networks/bitcoin/tsconfig.json b/packages/networks/bitcoin/tsconfig.json new file mode 100644 index 0000000..e40c547 --- /dev/null +++ b/packages/networks/bitcoin/tsconfig.json @@ -0,0 +1,21 @@ +{ + "compilerOptions": { + "noEmit": true, + "composite": true, + "declaration": true, + "outDir": "./dist/esm", + "declarationDir": "./dist/types" + }, + "extends": "../../../tsconfig.json", + "include": [ + "src", + ".eslintrc.json", + "tests", + "vite.config.ts", + "esbuild.ts", + "vitest.config.ts", + "../../../esbuild.ts", + "../../../vite.config.ts", + "../../../vitest.config.ts", + ] +} diff --git a/packages/networks/bitcoin/vite.config.ts b/packages/networks/bitcoin/vite.config.ts new file mode 100644 index 0000000..87de654 --- /dev/null +++ b/packages/networks/bitcoin/vite.config.ts @@ -0,0 +1,10 @@ +import { mergeConfig } from 'vite' +import mainConfig from '../../../vite.config.ts' + +export default mergeConfig(mainConfig, { + build: { + lib: { + name: 'Bitcoin' + } + } +}) diff --git a/packages/networks/bitcoin/vite.svg b/packages/networks/bitcoin/vite.svg new file mode 100644 index 0000000..e7b8dfb --- /dev/null +++ b/packages/networks/bitcoin/vite.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/packages/networks/bitcoin/vitest.config.ts b/packages/networks/bitcoin/vitest.config.ts new file mode 100644 index 0000000..73ee32b --- /dev/null +++ b/packages/networks/bitcoin/vitest.config.ts @@ -0,0 +1,11 @@ +import { mergeConfig, defineConfig } from 'vitest/config' +import mainConfig from '../../../vite.config.ts' + +export default mergeConfig( + mainConfig, + defineConfig({ + test: { + setupFiles: ['./tests/setup.ts'] + } + }) +) From 07a2f8686c056a01b4d318b4db249f297b3b24ac Mon Sep 17 00:00:00 2001 From: Halil Beycan <50718965+BeycanDeveloper@users.noreply.github.com> Date: Fri, 10 May 2024 12:07:48 +0800 Subject: [PATCH 05/90] updated --- packages/networks/boilerplate/tests/setup.ts | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/packages/networks/boilerplate/tests/setup.ts b/packages/networks/boilerplate/tests/setup.ts index e69de29..6c04b6b 100644 --- a/packages/networks/boilerplate/tests/setup.ts +++ b/packages/networks/boilerplate/tests/setup.ts @@ -0,0 +1,13 @@ +import { Provider } from '../src/services/Provider.ts' + +let provider: Provider + +try { + provider = Provider.instance +} catch (e) { + provider = new Provider({ + testnet: true + }) +} + +export { provider } From 395cc25737dca7988df15efbfcfd41ed3d46fa23 Mon Sep 17 00:00:00 2001 From: Halil Beycan <50718965+BeycanDeveloper@users.noreply.github.com> Date: Fri, 10 May 2024 12:09:07 +0800 Subject: [PATCH 06/90] updated --- packages/networks/tron/tests/services.spec.ts | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/packages/networks/tron/tests/services.spec.ts b/packages/networks/tron/tests/services.spec.ts index e94f8f9..37d09f4 100644 --- a/packages/networks/tron/tests/services.spec.ts +++ b/packages/networks/tron/tests/services.spec.ts @@ -13,14 +13,10 @@ describe('Provider', () => { }) it('checkRpcConnection', async () => { - expect( - await provider.checkRpcConnection(process.env.EVM_RPC_URL as unknown as string) - ).toBe(true) + expect(await provider.checkRpcConnection()).toBe(true) }) it('checkWsConnection', async () => { - expect(await provider.checkWsConnection(process.env.EVM_WS_URL as unknown as string)).toBe( - true - ) + expect(await provider.checkWsConnection()).toBe(true) }) }) From ba76637ccc3a999913c46aa3030d82d856ae547b Mon Sep 17 00:00:00 2001 From: Halil Beycan <50718965+BeycanDeveloper@users.noreply.github.com> Date: Fri, 10 May 2024 12:12:46 +0800 Subject: [PATCH 07/90] updated --- packages/networks/boilerplate/src/services/Provider.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/networks/boilerplate/src/services/Provider.ts b/packages/networks/boilerplate/src/services/Provider.ts index 9377756..d92d40d 100644 --- a/packages/networks/boilerplate/src/services/Provider.ts +++ b/packages/networks/boilerplate/src/services/Provider.ts @@ -19,7 +19,7 @@ export class Provider implements ProviderInterface { * @param network - Network configuration of the provider */ constructor(network: NetworkConfigInterface) { - this.network = network + this.update(network) } /** @@ -69,6 +69,7 @@ export class Provider implements ProviderInterface { */ update(network: NetworkConfigInterface): void { this.network = network + Provider._instance = this } /** From a49b19397e1dfc6162b5a59bbb739c2c36b81ab8 Mon Sep 17 00:00:00 2001 From: Halil Beycan <50718965+BeycanDeveloper@users.noreply.github.com> Date: Fri, 10 May 2024 12:13:34 +0800 Subject: [PATCH 08/90] bitcoin provider created --- .env.example | 11 +- packages/networks/bitcoin/package-lock.json | 497 ++++++++++++++++++ .../networks/bitcoin/src/services/Provider.ts | 88 +++- .../networks/bitcoin/tests/services.spec.ts | 21 +- packages/networks/bitcoin/tests/setup.ts | 13 + vitest.config.ts | 1 + 6 files changed, 613 insertions(+), 18 deletions(-) create mode 100644 packages/networks/bitcoin/package-lock.json diff --git a/.env.example b/.env.example index 0e20491..249afc2 100644 --- a/.env.example +++ b/.env.example @@ -82,4 +82,13 @@ TRON_MODEL_TEST_RECEIVER='TS1WYZNoNw32hog68m5GyhwZnkhf6HNzhi' TRON_TRX_TRANSFER_TX='8697ad2c4e1713227c16a65a5845636458df2d3db3adf526e07e17699bc6b3c4' TRON_TOKEN_TRANSFER_TX='bd0ba6ebb8d2f910b27de1565c66cc89337b792dfdb6484847c817ccbd240760' TRON_NFT_TRANSFER_TX='d5dd97c09efdb93f36808a9f8e14642ef226880aa91a846583d4ce98c0084637' -#TRON \ No newline at end of file +#TRON + +#Bitcoin +BTC_TRANSFER_TEST_IS_ACTIVE=false +BTC_BLOCKCYPHER_TOKEN='49d43a59a4f24d31a9731eb067ab971c' +BTC_SENDER_PRIVATE_KEY='cNHUtnWqwAwGajUGjyHLNbUcfHaDC3ujqjc6qcZik5Xa58Hj46vG' +BTC_SENDER_ADDRESS='tb1q8juz7c302wdcpfz83zvvyf4jxc8sfq4wyth3pr' +BTC_RECEIVER_ADDRESS='tb1q9uxj8p043sjkm0qzlsys7677mv98j76k8cvgtg' +BTC_TRANSFER_AMOUNT=0.00001 +#Bitcoin \ No newline at end of file diff --git a/packages/networks/bitcoin/package-lock.json b/packages/networks/bitcoin/package-lock.json new file mode 100644 index 0000000..61bed1b --- /dev/null +++ b/packages/networks/bitcoin/package-lock.json @@ -0,0 +1,497 @@ +{ + "name": "@multiplechain/bitcoin", + "version": "0.1.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "@multiplechain/bitcoin", + "version": "0.1.0", + "license": "MIT", + "dependencies": { + "@multiplechain/types": "^0.1.55", + "@multiplechain/utils": "^0.1.18" + } + }, + "node_modules/@multiplechain/types": { + "version": "0.1.55", + "resolved": "https://registry.npmjs.org/@multiplechain/types/-/types-0.1.55.tgz", + "integrity": "sha512-9fYrLaDxX2pj9zfIbmvk1hPF3FH/bK+Q3uTF+k3zdsitP/HzQ1S9zImNz20Tvoqkk1ns+/8ecE0Y6GNowsDOQA==" + }, + "node_modules/@multiplechain/utils": { + "version": "0.1.18", + "resolved": "https://registry.npmjs.org/@multiplechain/utils/-/utils-0.1.18.tgz", + "integrity": "sha512-UCoOOBJrawp/lInepxuoEiYwId0wMPg7rX8p78FLqzGl8f/b93sAtv7sP87/VVKwhdoEuNZ/uQjckycmNeks/w==", + "dependencies": { + "@types/ws": "^8.5.10", + "bignumber.js": "^9.1.2", + "web3-utils": "^4.2.0", + "ws": "^8.16.0" + } + }, + "node_modules/@noble/curves": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.3.0.tgz", + "integrity": "sha512-t01iSXPuN+Eqzb4eBX0S5oubSqXbK/xXa1Ne18Hj8f9pStxztHCE2gfboSp/dZRLSqfuLpRK2nDXDK+W9puocA==", + "dependencies": { + "@noble/hashes": "1.3.3" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@noble/hashes": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.3.tgz", + "integrity": "sha512-V7/fPHgl+jsVPXqqeOzT8egNj2iBIVt+ECeMMG8TdcnTikP3oaBtUVqpT/gYCR68aEBJSF+XbYUxStjbFMqIIA==", + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@scure/base": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/@scure/base/-/base-1.1.6.tgz", + "integrity": "sha512-ok9AWwhcgYuGG3Zfhyqg+zwl+Wn5uE+dwC0NV/2qQkx4dABbb/bx96vWu8NSj+BNjjSjno+JRYRjle1jV08k3g==", + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@scure/bip32": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@scure/bip32/-/bip32-1.3.3.tgz", + "integrity": "sha512-LJaN3HwRbfQK0X1xFSi0Q9amqOgzQnnDngIt+ZlsBC3Bm7/nE7K0kwshZHyaru79yIVRv/e1mQAjZyuZG6jOFQ==", + "dependencies": { + "@noble/curves": "~1.3.0", + "@noble/hashes": "~1.3.2", + "@scure/base": "~1.1.4" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@scure/bip39": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@scure/bip39/-/bip39-1.2.2.tgz", + "integrity": "sha512-HYf9TUXG80beW+hGAt3TRM8wU6pQoYur9iNypTROm42dorCGmLnFe3eWjz3gOq6G62H2WRh0FCzAR1PI+29zIA==", + "dependencies": { + "@noble/hashes": "~1.3.2", + "@scure/base": "~1.1.4" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@types/node": { + "version": "20.12.11", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.12.11.tgz", + "integrity": "sha512-vDg9PZ/zi+Nqp6boSOT7plNuthRugEKixDv5sFTIpkE89MmNtEArAShI4mxuX2+UrLEe9pxC1vm2cjm9YlWbJw==", + "dependencies": { + "undici-types": "~5.26.4" + } + }, + "node_modules/@types/ws": { + "version": "8.5.10", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.10.tgz", + "integrity": "sha512-vmQSUcfalpIq0R9q7uTo2lXs6eGIpt9wtnLdMv9LVpIjCA/+ufZRozlVoVelIYixx1ugCBKDhn89vnsEGOCx9A==", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/available-typed-arrays": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", + "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", + "dependencies": { + "possible-typed-array-names": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/bignumber.js": { + "version": "9.1.2", + "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.1.2.tgz", + "integrity": "sha512-2/mKyZH9K85bzOEfhXDBFZTGd1CTs+5IHpeFQo9luiBG7hghdC851Pj2WAhb6E3R6b9tZj/XKhbg4fum+Kepug==", + "engines": { + "node": "*" + } + }, + "node_modules/call-bind": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", + "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "set-function-length": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/define-data-property": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/es-define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", + "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", + "dependencies": { + "get-intrinsic": "^1.2.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/ethereum-cryptography": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-2.1.3.tgz", + "integrity": "sha512-BlwbIL7/P45W8FGW2r7LGuvoEZ+7PWsniMvQ4p5s2xCyw9tmaDlpfsN9HjAucbF+t/qpVHwZUisgfK24TCW8aA==", + "dependencies": { + "@noble/curves": "1.3.0", + "@noble/hashes": "1.3.3", + "@scure/bip32": "1.3.3", + "@scure/bip39": "1.2.2" + } + }, + "node_modules/eventemitter3": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz", + "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==" + }, + "node_modules/for-each": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", + "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", + "dependencies": { + "is-callable": "^1.1.3" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-intrinsic": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", + "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "hasown": "^2.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/gopd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", + "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", + "dependencies": { + "get-intrinsic": "^1.1.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-property-descriptors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", + "dependencies": { + "es-define-property": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-proto": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", + "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "dependencies": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "node_modules/is-arguments": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz", + "integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==", + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-callable": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", + "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-generator-function": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz", + "integrity": "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==", + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-typed-array": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.13.tgz", + "integrity": "sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw==", + "dependencies": { + "which-typed-array": "^1.1.14" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/possible-typed-array-names": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz", + "integrity": "sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/set-function-length": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", + "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/undici-types": { + "version": "5.26.5", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==" + }, + "node_modules/util": { + "version": "0.12.5", + "resolved": "https://registry.npmjs.org/util/-/util-0.12.5.tgz", + "integrity": "sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA==", + "dependencies": { + "inherits": "^2.0.3", + "is-arguments": "^1.0.4", + "is-generator-function": "^1.0.7", + "is-typed-array": "^1.1.3", + "which-typed-array": "^1.1.2" + } + }, + "node_modules/web3-errors": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/web3-errors/-/web3-errors-1.1.4.tgz", + "integrity": "sha512-WahtszSqILez+83AxGecVroyZsMuuRT+KmQp4Si5P4Rnqbczno1k748PCrZTS1J4UCPmXMG2/Vt+0Bz2zwXkwQ==", + "dependencies": { + "web3-types": "^1.3.1" + }, + "engines": { + "node": ">=14", + "npm": ">=6.12.0" + } + }, + "node_modules/web3-types": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/web3-types/-/web3-types-1.6.0.tgz", + "integrity": "sha512-qgOtADqlD5hw+KPKBUGaXAcdNLL0oh6qTeVgXwewCfbL/lG9R+/GrgMQB1gbTJ3cit8hMwtH8KX2Em6OwO0HRw==", + "engines": { + "node": ">=14", + "npm": ">=6.12.0" + } + }, + "node_modules/web3-utils": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-4.2.3.tgz", + "integrity": "sha512-m5plKTC2YtQntHITQRyIePw52UVP1IrShhmA2FACtn4zmc5ADmrXOlQWiPzxFP/18eRJsAaUAw2+CQn1u4WPxQ==", + "dependencies": { + "ethereum-cryptography": "^2.0.0", + "eventemitter3": "^5.0.1", + "web3-errors": "^1.1.4", + "web3-types": "^1.6.0", + "web3-validator": "^2.0.5" + }, + "engines": { + "node": ">=14", + "npm": ">=6.12.0" + } + }, + "node_modules/web3-validator": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/web3-validator/-/web3-validator-2.0.5.tgz", + "integrity": "sha512-2gLOSW8XqEN5pw5jVUm20EB7A8SbQiekpAtiI0JBmCIV0a2rp97v8FgWY5E3UEqnw5WFfEqvcDVW92EyynDTyQ==", + "dependencies": { + "ethereum-cryptography": "^2.0.0", + "util": "^0.12.5", + "web3-errors": "^1.1.4", + "web3-types": "^1.5.0", + "zod": "^3.21.4" + }, + "engines": { + "node": ">=14", + "npm": ">=6.12.0" + } + }, + "node_modules/which-typed-array": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.15.tgz", + "integrity": "sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA==", + "dependencies": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/ws": { + "version": "8.17.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.0.tgz", + "integrity": "sha512-uJq6108EgZMAl20KagGkzCKfMEjxmKvZHG7Tlq0Z6nOky7YF7aq4mOx6xK8TJ/i1LeK4Qus7INktacctDgY8Ow==", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/zod": { + "version": "3.23.8", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.23.8.tgz", + "integrity": "sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g==", + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } + } + } +} diff --git a/packages/networks/bitcoin/src/services/Provider.ts b/packages/networks/bitcoin/src/services/Provider.ts index 9377756..d239860 100644 --- a/packages/networks/bitcoin/src/services/Provider.ts +++ b/packages/networks/bitcoin/src/services/Provider.ts @@ -1,14 +1,36 @@ -import { - ErrorTypeEnum, - type NetworkConfigInterface, - type ProviderInterface -} from '@multiplechain/types' +import { checkWebSocket } from '@multiplechain/utils' +import { ErrorTypeEnum, type ProviderInterface } from '@multiplechain/types' -export class Provider implements ProviderInterface { +export interface BitcoinNetworkConfigInterface { + testnet: boolean + blockCypherToken?: string +} + +export class Provider implements Omit { /** * Network configuration of the provider */ - network: NetworkConfigInterface + network: BitcoinNetworkConfigInterface + + /** + * API URL + */ + api: string + + /** + * Explorer URL + */ + explorer: string + + /** + * Websocket URL + */ + wsUrl: string + + /** + * BlockCypher token + */ + blockCypherToken?: string /** * Static instance of the provider @@ -18,8 +40,8 @@ export class Provider implements ProviderInterface { /** * @param network - Network configuration of the provider */ - constructor(network: NetworkConfigInterface) { - this.network = network + constructor(network: BitcoinNetworkConfigInterface) { + this.update(network) } /** @@ -35,10 +57,10 @@ export class Provider implements ProviderInterface { /** * Initialize the static instance of the provider - * @param {NetworkConfigInterface} network - Network configuration of the provider + * @param {BitcoinNetworkConfigInterface} network - Network configuration of the provider * @returns {void} */ - static initialize(network: NetworkConfigInterface): void { + static initialize(network: BitcoinNetworkConfigInterface): void { if (Provider._instance !== undefined) { throw new Error(ErrorTypeEnum.PROVIDER_IS_ALREADY_INITIALIZED) } @@ -51,7 +73,17 @@ export class Provider implements ProviderInterface { * @returns {Promise} */ async checkRpcConnection(url?: string): Promise { - return true + try { + const response = await fetch(url ?? this.api + 'block-height/0') + + if (!response.ok) { + return new Error(response.statusText + ': ' + (await response.text())) + } + + return true + } catch (error) { + return error as Error + } } /** @@ -60,15 +92,43 @@ export class Provider implements ProviderInterface { * @returns {Promise} */ async checkWsConnection(url?: string): Promise { - return true + try { + const result: any = await checkWebSocket(url ?? this.wsUrl) + + if (result instanceof Error) { + return result + } + + return true + } catch (error) { + return error as Error + } } /** * Update network configuration of the provider * @param network - Network configuration of the provider */ - update(network: NetworkConfigInterface): void { + update(network: BitcoinNetworkConfigInterface): void { this.network = network + Provider._instance = this + this.blockCypherToken = this.network.blockCypherToken + if (this.network.testnet) { + this.api = 'https://blockstream.info/testnet/api/' + this.explorer = 'https://blockstream.info/testnet/' + const token = this.network.blockCypherToken ?? '49d43a59a4f24d31a9731eb067ab971c' + this.wsUrl = 'wss://socket.blockcypher.com/v1/btc/test3?token=' + token + } else { + this.api = 'https://blockstream.info/api/' + this.explorer = 'https://blockstream.info/' + if (this.network.blockCypherToken !== undefined) { + this.wsUrl = + 'wss://socket.blockcypher.com/v1/btc/main?token=' + + this.network.blockCypherToken + } else { + this.wsUrl = 'wss://ws.blockchain.info/inv' + } + } } /** diff --git a/packages/networks/bitcoin/tests/services.spec.ts b/packages/networks/bitcoin/tests/services.spec.ts index 34c5579..37d09f4 100644 --- a/packages/networks/bitcoin/tests/services.spec.ts +++ b/packages/networks/bitcoin/tests/services.spec.ts @@ -1,7 +1,22 @@ import { describe, it, expect } from 'vitest' -describe('example', () => { - it('should work', () => { - expect(1 + 1).toBe(2) +import { provider } from './setup.ts' +import { Provider } from '../src/services/Provider.ts' + +describe('Provider', () => { + it('isTestnet', () => { + expect(provider.isTestnet()).toBe(true) + }) + + it('instance', () => { + expect(Provider.instance).toBe(provider) + }) + + it('checkRpcConnection', async () => { + expect(await provider.checkRpcConnection()).toBe(true) + }) + + it('checkWsConnection', async () => { + expect(await provider.checkWsConnection()).toBe(true) }) }) diff --git a/packages/networks/bitcoin/tests/setup.ts b/packages/networks/bitcoin/tests/setup.ts index e69de29..6c04b6b 100644 --- a/packages/networks/bitcoin/tests/setup.ts +++ b/packages/networks/bitcoin/tests/setup.ts @@ -0,0 +1,13 @@ +import { Provider } from '../src/services/Provider.ts' + +let provider: Provider + +try { + provider = Provider.instance +} catch (e) { + provider = new Provider({ + testnet: true + }) +} + +export { provider } diff --git a/vitest.config.ts b/vitest.config.ts index a2e156a..4d5bf13 100644 --- a/vitest.config.ts +++ b/vitest.config.ts @@ -24,6 +24,7 @@ export default mergeConfig( root: fileURLToPath(new URL('./', import.meta.url)), setupFiles: [ './packages/networks/evm-chains/tests/setup.ts', + './packages/networks/bitcoin/tests/setup.ts', './packages/networks/tron/tests/setup.ts' ] } From 84c6b40f6215690c0c831138ac2a7a0c0f757006 Mon Sep 17 00:00:00 2001 From: Halil Beycan <50718965+BeycanDeveloper@users.noreply.github.com> Date: Fri, 10 May 2024 15:18:33 +0800 Subject: [PATCH 09/90] coin completed --- packages/networks/bitcoin/package.json | 9 +- packages/networks/bitcoin/pnpm-lock.yaml | 204 +++++++++++++++++- packages/networks/bitcoin/src/assets/Coin.ts | 72 ++++++- .../networks/bitcoin/src/services/Provider.ts | 16 +- .../bitcoin/src/services/TransactionSigner.ts | 34 ++- .../networks/bitcoin/tests/assets.spec.ts | 64 +++++- 6 files changed, 372 insertions(+), 27 deletions(-) diff --git a/packages/networks/bitcoin/package.json b/packages/networks/bitcoin/package.json index dc08308..965358e 100644 --- a/packages/networks/bitcoin/package.json +++ b/packages/networks/bitcoin/package.json @@ -63,6 +63,11 @@ }, "dependencies": { "@multiplechain/types": "^0.1.55", - "@multiplechain/utils": "^0.1.18" + "@multiplechain/utils": "^0.1.18", + "axios": "^1.6.8", + "bitcore-lib": "^10.0.28" + }, + "devDependencies": { + "@types/bitcore-lib": "^0.15.6" } -} \ No newline at end of file +} diff --git a/packages/networks/bitcoin/pnpm-lock.yaml b/packages/networks/bitcoin/pnpm-lock.yaml index aae81e5..463578a 100644 --- a/packages/networks/bitcoin/pnpm-lock.yaml +++ b/packages/networks/bitcoin/pnpm-lock.yaml @@ -11,6 +11,17 @@ dependencies: '@multiplechain/utils': specifier: ^0.1.18 version: 0.1.18 + axios: + specifier: ^1.6.8 + version: 1.6.8 + bitcore-lib: + specifier: ^10.0.28 + version: 10.0.28 + +devDependencies: + '@types/bitcore-lib': + specifier: ^0.15.6 + version: 0.15.6 packages: @@ -60,11 +71,16 @@ packages: '@scure/base': 1.1.6 dev: false + /@types/bitcore-lib@0.15.6: + resolution: {integrity: sha512-CtKDBgSBubPXZ0wFeCiUCSdzH+cuy6nFya3FboOqf44evi+OmkQPqEg3ASMpmPDYE8vkcxV302Iu8lZqCjYieg==} + dependencies: + '@types/node': 20.12.7 + dev: true + /@types/node@20.12.7: resolution: {integrity: sha512-wq0cICSkRLVaf3UGLMGItu/PtdY7oaXaI/RVU+xliKVOtRna3PRY57ZDfztpDL0n11vfymMUnXv8QwYCO7L1wg==} dependencies: undici-types: 5.26.5 - dev: false /@types/ws@8.5.10: resolution: {integrity: sha512-vmQSUcfalpIq0R9q7uTo2lXs6eGIpt9wtnLdMv9LVpIjCA/+ufZRozlVoVelIYixx1ugCBKDhn89vnsEGOCx9A==} @@ -72,6 +88,10 @@ packages: '@types/node': 20.12.7 dev: false + /asynckit@0.4.0: + resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} + dev: false + /available-typed-arrays@1.0.7: resolution: {integrity: sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==} engines: {node: '>= 0.4'} @@ -79,10 +99,80 @@ packages: possible-typed-array-names: 1.0.0 dev: false + /axios@1.6.8: + resolution: {integrity: sha512-v/ZHtJDU39mDpyBoFVkETcd/uNdxrWRrg3bKpOKzXFA6Bvqopts6ALSMU3y6ijYxbw2B+wPrIv46egTzJXCLGQ==} + dependencies: + follow-redirects: 1.15.6 + form-data: 4.0.0 + proxy-from-env: 1.1.0 + transitivePeerDependencies: + - debug + dev: false + + /base-x@3.0.9: + resolution: {integrity: sha512-H7JU6iBHTal1gp56aKoaa//YUxEaAOUiydvrV/pILqIHXTtqxSkATOnDA2u+jZ/61sD+L/412+7kzXRtWukhpQ==} + dependencies: + safe-buffer: 5.2.1 + dev: false + + /bech32@2.0.0: + resolution: {integrity: sha512-LcknSilhIGatDAsY1ak2I8VtGaHNhgMSYVxFrGLXv+xLHytaKZKcaUJJUE7qmBr7h33o5YQwP55pMI0xmkpJwg==} + dev: false + + /bigi@1.4.2: + resolution: {integrity: sha512-ddkU+dFIuEIW8lE7ZwdIAf2UPoM90eaprg5m3YXAVVTmKlqV/9BX4A2M8BOK2yOq6/VgZFVhK6QAxJebhlbhzw==} + dev: false + /bignumber.js@9.1.2: resolution: {integrity: sha512-2/mKyZH9K85bzOEfhXDBFZTGd1CTs+5IHpeFQo9luiBG7hghdC851Pj2WAhb6E3R6b9tZj/XKhbg4fum+Kepug==} dev: false + /bip-schnorr@0.6.4: + resolution: {integrity: sha512-dNKw7Lea8B0wMIN4OjEmOk/Z5qUGqoPDY0P2QttLqGk1hmDPytLWW8PR5Pb6Vxy6CprcdEgfJpOjUu+ONQveyg==} + engines: {node: '>=8.0.0'} + dependencies: + bigi: 1.4.2 + ecurve: 1.0.6 + js-sha256: 0.9.0 + randombytes: 2.1.0 + safe-buffer: 5.2.1 + dev: false + + /bitcore-lib@10.0.28: + resolution: {integrity: sha512-uOWHpWbUxEj411p+tp6DCb9NfZdsCAHl6Z/rs96mquQMsef29fOqWUyk4Bl7yLf+KwzU5ZKy0HIPnjGFlmpXpg==} + dependencies: + bech32: 2.0.0 + bip-schnorr: 0.6.4 + bn.js: 4.11.8 + bs58: 4.0.1 + buffer-compare: 1.1.1 + elliptic: 6.5.5 + inherits: 2.0.1 + lodash: 4.17.21 + dev: false + + /bn.js@4.11.8: + resolution: {integrity: sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==} + dev: false + + /bn.js@4.12.0: + resolution: {integrity: sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==} + dev: false + + /brorand@1.1.0: + resolution: {integrity: sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w==} + dev: false + + /bs58@4.0.1: + resolution: {integrity: sha512-Ok3Wdf5vOIlBrgCvTq96gBkJw+JUEzdBgyaza5HLtPm7yTHkjRy8+JzNyHF7BHa0bNWOQIp3m5YF0nnFcOIKLw==} + dependencies: + base-x: 3.0.9 + dev: false + + /buffer-compare@1.1.1: + resolution: {integrity: sha512-O6NvNiHZMd3mlIeMDjP6t/gPG75OqGPeiRZXoMQZJ6iy9GofCls4Ijs5YkPZZwoysizLiedhticmdyx/GyHghA==} + dev: false + /call-bind@1.0.7: resolution: {integrity: sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==} engines: {node: '>= 0.4'} @@ -94,6 +184,13 @@ packages: set-function-length: 1.2.2 dev: false + /combined-stream@1.0.8: + resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==} + engines: {node: '>= 0.8'} + dependencies: + delayed-stream: 1.0.0 + dev: false + /define-data-property@1.1.4: resolution: {integrity: sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==} engines: {node: '>= 0.4'} @@ -103,6 +200,30 @@ packages: gopd: 1.0.1 dev: false + /delayed-stream@1.0.0: + resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} + engines: {node: '>=0.4.0'} + dev: false + + /ecurve@1.0.6: + resolution: {integrity: sha512-/BzEjNfiSuB7jIWKcS/z8FK9jNjmEWvUV2YZ4RLSmcDtP7Lq0m6FvDuSnJpBlDpGRpfRQeTLGLBI8H+kEv0r+w==} + dependencies: + bigi: 1.4.2 + safe-buffer: 5.2.1 + dev: false + + /elliptic@6.5.5: + resolution: {integrity: sha512-7EjbcmUm17NQFu4Pmgmq2olYMj8nwMnpcddByChSUjArp8F5DQWcIcpriwO4ZToLNAJig0yiyjswfyGNje/ixw==} + dependencies: + bn.js: 4.12.0 + brorand: 1.1.0 + hash.js: 1.1.7 + hmac-drbg: 1.0.1 + inherits: 2.0.4 + minimalistic-assert: 1.0.1 + minimalistic-crypto-utils: 1.0.1 + dev: false + /es-define-property@1.0.0: resolution: {integrity: sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==} engines: {node: '>= 0.4'} @@ -128,12 +249,31 @@ packages: resolution: {integrity: sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==} dev: false + /follow-redirects@1.15.6: + resolution: {integrity: sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==} + engines: {node: '>=4.0'} + peerDependencies: + debug: '*' + peerDependenciesMeta: + debug: + optional: true + dev: false + /for-each@0.3.3: resolution: {integrity: sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==} dependencies: is-callable: 1.2.7 dev: false + /form-data@4.0.0: + resolution: {integrity: sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==} + engines: {node: '>= 6'} + dependencies: + asynckit: 0.4.0 + combined-stream: 1.0.8 + mime-types: 2.1.35 + dev: false + /function-bind@1.1.2: resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} dev: false @@ -178,6 +318,13 @@ packages: has-symbols: 1.0.3 dev: false + /hash.js@1.1.7: + resolution: {integrity: sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==} + dependencies: + inherits: 2.0.4 + minimalistic-assert: 1.0.1 + dev: false + /hasown@2.0.2: resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} engines: {node: '>= 0.4'} @@ -185,6 +332,18 @@ packages: function-bind: 1.1.2 dev: false + /hmac-drbg@1.0.1: + resolution: {integrity: sha512-Tti3gMqLdZfhOQY1Mzf/AanLiqh1WTiJgEj26ZuYQ9fbkLomzGchCws4FyrSd4VkpBfiNhaE1On+lOz894jvXg==} + dependencies: + hash.js: 1.1.7 + minimalistic-assert: 1.0.1 + minimalistic-crypto-utils: 1.0.1 + dev: false + + /inherits@2.0.1: + resolution: {integrity: sha512-8nWq2nLTAwd02jTqJExUYFSD/fKq6VH9Y/oG2accc/kdI0V98Bag8d5a4gi3XHz73rDWa2PvTtvcWYquKqSENA==} + dev: false + /inherits@2.0.4: resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} dev: false @@ -216,11 +375,53 @@ packages: which-typed-array: 1.1.15 dev: false + /js-sha256@0.9.0: + resolution: {integrity: sha512-sga3MHh9sgQN2+pJ9VYZ+1LPwXOxuBJBA5nrR5/ofPfuiJBE2hnjsaN8se8JznOmGLN2p49Pe5U/ttafcs/apA==} + dev: false + + /lodash@4.17.21: + resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} + dev: false + + /mime-db@1.52.0: + resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} + engines: {node: '>= 0.6'} + dev: false + + /mime-types@2.1.35: + resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} + engines: {node: '>= 0.6'} + dependencies: + mime-db: 1.52.0 + dev: false + + /minimalistic-assert@1.0.1: + resolution: {integrity: sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==} + dev: false + + /minimalistic-crypto-utils@1.0.1: + resolution: {integrity: sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg==} + dev: false + /possible-typed-array-names@1.0.0: resolution: {integrity: sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==} engines: {node: '>= 0.4'} dev: false + /proxy-from-env@1.1.0: + resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==} + dev: false + + /randombytes@2.1.0: + resolution: {integrity: sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==} + dependencies: + safe-buffer: 5.2.1 + dev: false + + /safe-buffer@5.2.1: + resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} + dev: false + /set-function-length@1.2.2: resolution: {integrity: sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==} engines: {node: '>= 0.4'} @@ -235,7 +436,6 @@ packages: /undici-types@5.26.5: resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==} - dev: false /util@0.12.5: resolution: {integrity: sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA==} diff --git a/packages/networks/bitcoin/src/assets/Coin.ts b/packages/networks/bitcoin/src/assets/Coin.ts index 1c2d8b3..7023cbb 100644 --- a/packages/networks/bitcoin/src/assets/Coin.ts +++ b/packages/networks/bitcoin/src/assets/Coin.ts @@ -1,5 +1,8 @@ +import axios from 'axios' +import { math } from '@multiplechain/utils' import { Provider } from '../services/Provider.ts' -import type { CoinInterface } from '@multiplechain/types' +import { Transaction, Script, Address } from 'bitcore-lib' +import { ErrorTypeEnum, type CoinInterface } from '@multiplechain/types' import { CoinTransactionSigner } from '../services/TransactionSigner.ts' export class Coin implements CoinInterface { @@ -19,21 +22,21 @@ export class Coin implements CoinInterface { * @returns {string} Coin name */ getName(): string { - return 'example' + return 'Bitcoin' } /** * @returns {string} Coin symbol */ getSymbol(): string { - return 'example' + return 'BTC' } /** * @returns {number} Decimal value of the coin */ getDecimals(): number { - return 18 + return 8 } /** @@ -41,7 +44,27 @@ export class Coin implements CoinInterface { * @returns {Promise} Wallet balance as currency of COIN */ async getBalance(owner: string): Promise { - return 0 + const addressStatsApi = this.provider.createEndpoint('address/' + owner) + const addressStats = await axios.get(addressStatsApi).then((res) => res.data) + const balanceSat = + addressStats.chain_stats.funded_txo_sum - addressStats.chain_stats.spent_txo_sum + return Coin.toBitcoin(balanceSat) + } + + /** + * @param {number} amount Amount in satoshi + * @returns {number} Amount in COIN + */ + static toBitcoin(amount: number): number { + return math.div(amount, 100000000, 8) + } + + /** + * @param {number} amount Amount in COIN + * @returns {number} Amount in satoshi + */ + static toSatoshi(amount: number): number { + return math.mul(amount, 100000000, 8) } /** @@ -55,6 +78,43 @@ export class Coin implements CoinInterface { receiver: string, amount: number ): Promise { - return new CoinTransactionSigner('example') + if (amount < 0) { + throw new Error(ErrorTypeEnum.INVALID_AMOUNT) + } + + if (amount > (await this.getBalance(sender))) { + throw new Error(ErrorTypeEnum.INSUFFICIENT_BALANCE) + } + + if (sender === receiver) { + throw new Error(ErrorTypeEnum.INVALID_ADDRESS) + } + + const inputs = [] + const transaction = new Transaction() + const senderAddress = new Address(sender) + const satoshiToSend = Coin.toSatoshi(amount) + + const utxos = await axios + .get(this.provider.createEndpoint('address/' + sender + '/utxo')) + .then((res) => res.data) + + for (const utxo of utxos) { + inputs.push( + new Transaction.UnspentOutput({ + txId: utxo.txid, + satoshis: utxo.value, + address: senderAddress, + outputIndex: utxo.vout, + script: Script.fromAddress(senderAddress) + }) + ) + } + + transaction.from(inputs) + transaction.change(sender) + transaction.to(receiver, satoshiToSend) + + return new CoinTransactionSigner(transaction) } } diff --git a/packages/networks/bitcoin/src/services/Provider.ts b/packages/networks/bitcoin/src/services/Provider.ts index d239860..93da6f3 100644 --- a/packages/networks/bitcoin/src/services/Provider.ts +++ b/packages/networks/bitcoin/src/services/Provider.ts @@ -1,3 +1,4 @@ +import axios from 'axios' import { checkWebSocket } from '@multiplechain/utils' import { ErrorTypeEnum, type ProviderInterface } from '@multiplechain/types' @@ -74,10 +75,10 @@ export class Provider implements Omit { */ async checkRpcConnection(url?: string): Promise { try { - const response = await fetch(url ?? this.api + 'block-height/0') + const response = await axios.get(url ?? this.api + 'block-height/0') - if (!response.ok) { - return new Error(response.statusText + ': ' + (await response.text())) + if (response.status !== 200) { + return new Error(response.statusText + ': ' + JSON.stringify(response.data)) } return true @@ -131,6 +132,15 @@ export class Provider implements Omit { } } + /** + * Create a new endpoint + * @param {string} endpoint - Endpoint + * @returns {string} Endpoint + */ + createEndpoint(endpoint: string): string { + return this.api + endpoint + } + /** * Get the current network configuration is testnet or not * @returns boolean diff --git a/packages/networks/bitcoin/src/services/TransactionSigner.ts b/packages/networks/bitcoin/src/services/TransactionSigner.ts index a76019e..7f2356d 100644 --- a/packages/networks/bitcoin/src/services/TransactionSigner.ts +++ b/packages/networks/bitcoin/src/services/TransactionSigner.ts @@ -1,20 +1,23 @@ +import axios from 'axios' +import type { AxiosError } from 'axios' import { Provider } from '../services/Provider.ts' import { Transaction } from '../models/Transaction.ts' import { NftTransaction } from '../models/NftTransaction.ts' import { CoinTransaction } from '../models/CoinTransaction.ts' import { TokenTransaction } from '../models/TokenTransaction.ts' -import type { TransactionSignerInterface } from '@multiplechain/types' +import type { Transaction as TransactionData } from 'bitcore-lib' +import { type TransactionSignerInterface } from '@multiplechain/types' export class TransactionSigner implements TransactionSignerInterface { /** * Transaction data from the blockchain network */ - rawData: any + rawData: TransactionData /** * Signed transaction data */ - signedData?: any + signedData?: string /** * Blockchain network provider @@ -22,9 +25,9 @@ export class TransactionSigner implements TransactionSignerInterface { provider: Provider /** - * @param {any} rawData - Transaction data + * @param {TransactionData} rawData - Transaction data */ - constructor(rawData: any, provider?: Provider) { + constructor(rawData: TransactionData, provider?: Provider) { this.rawData = rawData this.provider = provider ?? Provider.instance } @@ -35,7 +38,9 @@ export class TransactionSigner implements TransactionSignerInterface { * @returns {Promise} Signed transaction data */ async sign(privateKey: string): Promise { - return await Promise.resolve(this) + this.rawData.sign(privateKey) + this.signedData = this.rawData.serialize() + return this } /** @@ -43,14 +48,23 @@ export class TransactionSigner implements TransactionSignerInterface { * @returns {Promise} */ async send(): Promise { - return await Promise.resolve(new Transaction('example')) + try { + const result = await axios({ + method: 'POST', + url: `https://blockstream.info/testnet/api/tx`, + data: this.signedData + }) + return new Transaction(result.data.txid as string) + } catch (error: any) { + throw new Error(JSON.stringify((error as AxiosError).response?.data)) + } } /** * Get the raw transaction data * @returns Transaction data */ - getRawData(): any { + getRawData(): TransactionData { return this.rawData } @@ -58,8 +72,8 @@ export class TransactionSigner implements TransactionSignerInterface { * Get the signed transaction data * @returns Signed transaction data */ - getSignedData(): any { - return this.signedData + getSignedData(): string { + return this.signedData ?? '' } } diff --git a/packages/networks/bitcoin/tests/assets.spec.ts b/packages/networks/bitcoin/tests/assets.spec.ts index 34c5579..36147df 100644 --- a/packages/networks/bitcoin/tests/assets.spec.ts +++ b/packages/networks/bitcoin/tests/assets.spec.ts @@ -1,7 +1,63 @@ -import { describe, it, expect } from 'vitest' +import { describe, it, expect, assert } from 'vitest' -describe('example', () => { - it('should work', () => { - expect(1 + 1).toBe(2) +import { Coin } from '../src/assets/Coin.ts' +import { math } from '@multiplechain/utils' +import { Transaction } from '../src/models/Transaction.ts' +import { TransactionStatusEnum } from '@multiplechain/types' +import { TransactionSigner } from '../src/services/TransactionSigner.ts' + +const testAmount = Number(process.env.BTC_TRANSFER_AMOUNT) +const senderTestAddress = String(process.env.BTC_SENDER_ADDRESS) +const receiverTestAddress = String(process.env.BTC_RECEIVER_ADDRESS) +const senderPrivateKey = String(process.env.BTC_SENDER_PRIVATE_KEY) +const transferTestIsActive = Boolean(process.env.BTC_TRANSFER_TEST_IS_ACTIVE !== 'false') + +const checkSigner = async (signer: TransactionSigner, privateKey?: string): Promise => { + expect(signer).toBeInstanceOf(TransactionSigner) + + const rawData = signer.getRawData() + + assert.isObject(rawData) + + await signer.sign(privateKey ?? senderPrivateKey) + + assert.isString(signer.getSignedData()) +} + +const checkTx = async (transaction: Transaction): Promise => { + expect(transaction).toBeInstanceOf(Transaction) + const status = await transaction.wait(10 * 1000) + expect(status).toBe(TransactionStatusEnum.CONFIRMED) +} + +describe('Coin', () => { + const coin = new Coin() + it('Name and symbol', () => { + expect(coin.getName()).toBe('Bitcoin') + expect(coin.getSymbol()).toBe('BTC') + }) + + it('Decimals', () => { + expect(coin.getDecimals()).toBe(8) + }) + + it('Balance', async () => { + const balance = await coin.getBalance('tb1qc240vx54n08hnhx8l4rqxjzcxf4f0ssq5asawm') + expect(balance).toBe(0.00003) + }) + + it('Transfer', async () => { + const signer = await coin.transfer(senderTestAddress, receiverTestAddress, testAmount) + + await checkSigner(signer) + + if (!transferTestIsActive) return + + const beforeBalance = await coin.getBalance(receiverTestAddress) + + await checkTx(await signer.send()) + + const afterBalance = await coin.getBalance(receiverTestAddress) + expect(afterBalance).toBe(math.add(beforeBalance, testAmount)) }) }) From f8b0e13c94fddd5d8c801a437915f24a5febfb37 Mon Sep 17 00:00:00 2001 From: Halil Beycan <50718965+BeycanDeveloper@users.noreply.github.com> Date: Fri, 10 May 2024 15:28:16 +0800 Subject: [PATCH 10/90] updated fetch to axios --- packages/networks/evm-chains/package.json | 1 + packages/networks/evm-chains/pnpm-lock.yaml | 64 +++++++++++++++++++ .../evm-chains/src/services/Provider.ts | 21 +++--- 3 files changed, 73 insertions(+), 13 deletions(-) diff --git a/packages/networks/evm-chains/package.json b/packages/networks/evm-chains/package.json index 157848e..ff6c410 100644 --- a/packages/networks/evm-chains/package.json +++ b/packages/networks/evm-chains/package.json @@ -73,6 +73,7 @@ "@web3modal/core": "^4.1.11", "@web3modal/ethers": "^4.1.11", "@web3modal/scaffold-utils": "^4.1.11", + "axios": "^1.6.8", "ethers": "^6.11.1" } } \ No newline at end of file diff --git a/packages/networks/evm-chains/pnpm-lock.yaml b/packages/networks/evm-chains/pnpm-lock.yaml index 356b610..8412711 100644 --- a/packages/networks/evm-chains/pnpm-lock.yaml +++ b/packages/networks/evm-chains/pnpm-lock.yaml @@ -29,6 +29,9 @@ dependencies: '@web3modal/scaffold-utils': specifier: ^4.1.11 version: 4.1.11(react@18.2.0) + axios: + specifier: ^1.6.8 + version: 1.6.8 ethers: specifier: ^6.11.1 version: 6.11.1 @@ -1346,6 +1349,10 @@ packages: tslib: 2.4.0 dev: false + /asynckit@0.4.0: + resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} + dev: false + /atomic-sleep@1.0.0: resolution: {integrity: sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ==} engines: {node: '>=8.0.0'} @@ -1358,6 +1365,16 @@ packages: possible-typed-array-names: 1.0.0 dev: false + /axios@1.6.8: + resolution: {integrity: sha512-v/ZHtJDU39mDpyBoFVkETcd/uNdxrWRrg3bKpOKzXFA6Bvqopts6ALSMU3y6ijYxbw2B+wPrIv46egTzJXCLGQ==} + dependencies: + follow-redirects: 1.15.6 + form-data: 4.0.0 + proxy-from-env: 1.1.0 + transitivePeerDependencies: + - debug + dev: false + /base64-js@1.5.1: resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} dev: false @@ -1459,6 +1476,13 @@ packages: resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} dev: false + /combined-stream@1.0.8: + resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==} + engines: {node: '>= 0.8'} + dependencies: + delayed-stream: 1.0.0 + dev: false + /confbox@0.1.7: resolution: {integrity: sha512-uJcB/FKZtBMCJpK8MQji6bJHgu1tixKPxRLeGkNzBoOZzpnZUJm0jm2/sBDWcuBx1dYgxV4JU+g5hmNxCyAmdA==} dev: false @@ -1543,6 +1567,11 @@ packages: resolution: {integrity: sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg==} dev: false + /delayed-stream@1.0.0: + resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} + engines: {node: '>=0.4.0'} + dev: false + /destr@2.0.3: resolution: {integrity: sha512-2N3BOUU4gYMpTP24s5rF5iP7BDr7uNTCs4ozw3kf/eKfvWSIu93GEBi5m427YoyJoeOzQ5smuu4nNAPGb8idSQ==} dev: false @@ -1711,12 +1740,31 @@ packages: path-exists: 4.0.0 dev: false + /follow-redirects@1.15.6: + resolution: {integrity: sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==} + engines: {node: '>=4.0'} + peerDependencies: + debug: '*' + peerDependenciesMeta: + debug: + optional: true + dev: false + /for-each@0.3.3: resolution: {integrity: sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==} dependencies: is-callable: 1.2.7 dev: false + /form-data@4.0.0: + resolution: {integrity: sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==} + engines: {node: '>= 6'} + dependencies: + asynckit: 0.4.0 + combined-stream: 1.0.8 + mime-types: 2.1.35 + dev: false + /fsevents@2.3.3: resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} @@ -2097,6 +2145,18 @@ packages: picomatch: 2.3.1 dev: false + /mime-db@1.52.0: + resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} + engines: {node: '>= 0.6'} + dev: false + + /mime-types@2.1.35: + resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} + engines: {node: '>= 0.6'} + dependencies: + mime-db: 1.52.0 + dev: false + /mime@3.0.0: resolution: {integrity: sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A==} engines: {node: '>=10.0.0'} @@ -2337,6 +2397,10 @@ packages: resolution: {integrity: sha512-oyfc0Tx87Cpwva5ZXezSp5V9vht1c7dZBhvuV/y3ctkgMVUmiAGDVeeB0dKhGSyT0v1ZTEQYpe/RXlBVBNuCLA==} dev: false + /proxy-from-env@1.1.0: + resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==} + dev: false + /qrcode@1.5.3: resolution: {integrity: sha512-puyri6ApkEHYiVl4CFzo1tDkAZ+ATcnbJrJ6RiBM1Fhctdn/ix9MTE3hRph33omisEbC/2fcfemsseiKgBPKZg==} engines: {node: '>=10.13.0'} diff --git a/packages/networks/evm-chains/src/services/Provider.ts b/packages/networks/evm-chains/src/services/Provider.ts index ede4232..858087e 100644 --- a/packages/networks/evm-chains/src/services/Provider.ts +++ b/packages/networks/evm-chains/src/services/Provider.ts @@ -1,3 +1,4 @@ +import axios from 'axios' import { Ethers } from './Ethers.ts' import { ErrorTypeEnum, @@ -76,21 +77,15 @@ export class Provider implements Omit { */ async checkRpcConnection(url?: string): Promise { try { - const response = await fetch(url ?? this.network.rpcUrl, { - method: 'POST', - headers: { - 'Content-Type': 'application/json' - }, - body: JSON.stringify({ - jsonrpc: '2.0', - method: 'eth_getChainId', - params: [], - id: 1 - }) + const response = await axios.post(url ?? this.network.rpcUrl, { + jsonrpc: '2.0', + method: 'eth_blockNumber', + params: [], + id: 1 }) - if (!response.ok) { - return new Error(response.statusText + ': ' + (await response.text())) + if (response.status !== 200) { + return new Error(response.statusText + ': ' + JSON.stringify(response.data)) } return true From 7292b0acf8b24eaca1f1245bf3c94a9390314dd5 Mon Sep 17 00:00:00 2001 From: Halil Beycan <50718965+BeycanDeveloper@users.noreply.github.com> Date: Fri, 10 May 2024 15:30:35 +0800 Subject: [PATCH 11/90] added not implemented method exceptions --- packages/networks/bitcoin/src/assets/Contract.ts | 1 + .../networks/bitcoin/src/models/ContractTransaction.ts | 8 ++++++++ .../networks/bitcoin/src/services/TransactionListener.ts | 6 +++--- 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/packages/networks/bitcoin/src/assets/Contract.ts b/packages/networks/bitcoin/src/assets/Contract.ts index ee3a295..14044c0 100644 --- a/packages/networks/bitcoin/src/assets/Contract.ts +++ b/packages/networks/bitcoin/src/assets/Contract.ts @@ -19,6 +19,7 @@ export class Contract implements ContractInterface { constructor(address: string, provider?: Provider) { this.address = address this.provider = provider ?? Provider.instance + throw new Error('This class is not implemented for Bitcoin.') } /** diff --git a/packages/networks/bitcoin/src/models/ContractTransaction.ts b/packages/networks/bitcoin/src/models/ContractTransaction.ts index ad57241..fffd4f0 100644 --- a/packages/networks/bitcoin/src/models/ContractTransaction.ts +++ b/packages/networks/bitcoin/src/models/ContractTransaction.ts @@ -2,6 +2,14 @@ import { Transaction } from './Transaction.ts' import type { ContractTransactionInterface } from '@multiplechain/types' export class ContractTransaction extends Transaction implements ContractTransactionInterface { + /** + * @param {string} id Contract address + */ + constructor(id: string) { + super(id) + throw new Error('This class is not implemented for Bitcoin.') + } + /** * @returns {Promise} Contract address of the transaction */ diff --git a/packages/networks/bitcoin/src/services/TransactionListener.ts b/packages/networks/bitcoin/src/services/TransactionListener.ts index 47ee7d8..d680d46 100644 --- a/packages/networks/bitcoin/src/services/TransactionListener.ts +++ b/packages/networks/bitcoin/src/services/TransactionListener.ts @@ -121,7 +121,7 @@ export class TransactionListener * @returns {void} */ contractProcess(): void { - // Contract transaction process + throw new Error('This method is not implemented for Bitcoin.') } /** @@ -137,7 +137,7 @@ export class TransactionListener * @returns {void} */ tokenProcess(): void { - // Token transaction process + throw new Error('This method is not implemented for Bitcoin.') } /** @@ -145,6 +145,6 @@ export class TransactionListener * @returns {void} */ nftProcess(): void { - // NFT transaction process + throw new Error('This method is not implemented for Bitcoin.') } } From c63c5a2340b962c30aa644c974f20735b9ecef5d Mon Sep 17 00:00:00 2001 From: Halil Beycan <50718965+BeycanDeveloper@users.noreply.github.com> Date: Fri, 10 May 2024 17:20:55 +0800 Subject: [PATCH 12/90] models completed --- packages/networks/bitcoin/src/assets/Coin.ts | 22 +-- packages/networks/bitcoin/src/index.ts | 2 +- .../bitcoin/src/models/CoinTransaction.ts | 33 ++++- .../bitcoin/src/models/ContractTransaction.ts | 8 +- .../bitcoin/src/models/Transaction.ts | 125 ++++++++++++++++-- .../networks/bitcoin/src/services/Provider.ts | 2 +- .../bitcoin/src/services/TransactionSigner.ts | 2 +- packages/networks/bitcoin/src/utils.ts | 11 ++ .../networks/bitcoin/tests/models.spec.ts | 77 ++++++++++- packages/networks/bitcoin/vitest.config.ts | 1 + 10 files changed, 237 insertions(+), 46 deletions(-) create mode 100644 packages/networks/bitcoin/src/utils.ts diff --git a/packages/networks/bitcoin/src/assets/Coin.ts b/packages/networks/bitcoin/src/assets/Coin.ts index 7023cbb..d072142 100644 --- a/packages/networks/bitcoin/src/assets/Coin.ts +++ b/packages/networks/bitcoin/src/assets/Coin.ts @@ -1,6 +1,6 @@ import axios from 'axios' -import { math } from '@multiplechain/utils' import { Provider } from '../services/Provider.ts' +import { fromSatoshi, toSatoshi } from '../utils.ts' import { Transaction, Script, Address } from 'bitcore-lib' import { ErrorTypeEnum, type CoinInterface } from '@multiplechain/types' import { CoinTransactionSigner } from '../services/TransactionSigner.ts' @@ -48,23 +48,7 @@ export class Coin implements CoinInterface { const addressStats = await axios.get(addressStatsApi).then((res) => res.data) const balanceSat = addressStats.chain_stats.funded_txo_sum - addressStats.chain_stats.spent_txo_sum - return Coin.toBitcoin(balanceSat) - } - - /** - * @param {number} amount Amount in satoshi - * @returns {number} Amount in COIN - */ - static toBitcoin(amount: number): number { - return math.div(amount, 100000000, 8) - } - - /** - * @param {number} amount Amount in COIN - * @returns {number} Amount in satoshi - */ - static toSatoshi(amount: number): number { - return math.mul(amount, 100000000, 8) + return fromSatoshi(balanceSat) } /** @@ -93,7 +77,7 @@ export class Coin implements CoinInterface { const inputs = [] const transaction = new Transaction() const senderAddress = new Address(sender) - const satoshiToSend = Coin.toSatoshi(amount) + const satoshiToSend = toSatoshi(amount) const utxos = await axios .get(this.provider.createEndpoint('address/' + sender + '/utxo')) diff --git a/packages/networks/bitcoin/src/index.ts b/packages/networks/bitcoin/src/index.ts index 668ab52..7b0e1cd 100644 --- a/packages/networks/bitcoin/src/index.ts +++ b/packages/networks/bitcoin/src/index.ts @@ -4,5 +4,5 @@ export * as assets from './assets/index.ts' export * as models from './models/index.ts' export * as services from './services/index.ts' -export * as utils from '@multiplechain/utils' +export * as utils from './utils.ts' export * as types from '@multiplechain/types' diff --git a/packages/networks/bitcoin/src/models/CoinTransaction.ts b/packages/networks/bitcoin/src/models/CoinTransaction.ts index 9857f2e..d681e05 100644 --- a/packages/networks/bitcoin/src/models/CoinTransaction.ts +++ b/packages/networks/bitcoin/src/models/CoinTransaction.ts @@ -1,27 +1,30 @@ +import { fromSatoshi } from '../utils.ts' import { Transaction } from './Transaction.ts' import { TransactionStatusEnum } from '@multiplechain/types' -import type { AssetDirectionEnum, CoinTransactionInterface } from '@multiplechain/types' +import { AssetDirectionEnum, type CoinTransactionInterface } from '@multiplechain/types' export class CoinTransaction extends Transaction implements CoinTransactionInterface { /** * @returns {Promise} Wallet address of the receiver of transaction */ async getReceiver(): Promise { - return 'example' + const data = await this.getData() + return data?.vout[0].scriptpubkey_address ?? '' } /** * @returns {Promise} Wallet address of the sender of transaction */ async getSender(): Promise { - return 'example' + return await this.getSigner() } /** * @returns {Promise} Amount of coin that will be transferred */ async getAmount(): Promise { - return 0 + const data = await this.getData() + return fromSatoshi(data?.vout[0].value ?? 0) } /** @@ -35,6 +38,26 @@ export class CoinTransaction extends Transaction implements CoinTransactionInter address: string, amount: number ): Promise { - return TransactionStatusEnum.PENDING + const status = await this.getStatus() + + if (status === TransactionStatusEnum.PENDING) { + return TransactionStatusEnum.PENDING + } + + if ((await this.getAmount()) !== amount) { + return TransactionStatusEnum.FAILED + } + + if (direction === AssetDirectionEnum.INCOMING) { + if ((await this.getReceiver()).toLowerCase() !== address.toLowerCase()) { + return TransactionStatusEnum.FAILED + } + } else { + if ((await this.getSender()).toLowerCase() !== address.toLowerCase()) { + return TransactionStatusEnum.FAILED + } + } + + return TransactionStatusEnum.CONFIRMED } } diff --git a/packages/networks/bitcoin/src/models/ContractTransaction.ts b/packages/networks/bitcoin/src/models/ContractTransaction.ts index fffd4f0..4813a5a 100644 --- a/packages/networks/bitcoin/src/models/ContractTransaction.ts +++ b/packages/networks/bitcoin/src/models/ContractTransaction.ts @@ -1,12 +1,14 @@ import { Transaction } from './Transaction.ts' +import type { Provider } from '../services/Provider.ts' import type { ContractTransactionInterface } from '@multiplechain/types' export class ContractTransaction extends Transaction implements ContractTransactionInterface { /** - * @param {string} id Contract address + * @param {string} id Transaction id + * @param {Provider} provider Blockchain network provider */ - constructor(id: string) { - super(id) + constructor(id: string, provider?: Provider) { + super(id, provider) throw new Error('This class is not implemented for Bitcoin.') } diff --git a/packages/networks/bitcoin/src/models/Transaction.ts b/packages/networks/bitcoin/src/models/Transaction.ts index 15f111d..00b19c0 100644 --- a/packages/networks/bitcoin/src/models/Transaction.ts +++ b/packages/networks/bitcoin/src/models/Transaction.ts @@ -1,6 +1,50 @@ +import axios from 'axios' +import { fromSatoshi } from '../utils.ts' import { Provider } from '../services/Provider.ts' import type { TransactionInterface } from '@multiplechain/types' -import { TransactionStatusEnum } from '@multiplechain/types' +import { ErrorTypeEnum, TransactionStatusEnum } from '@multiplechain/types' + +export interface VinObject { + txid: string + vout: number + prevout: { + scriptpubkey: string + scriptpubkey_asm: string + scriptpubkey_type: string + scriptpubkey_address: string + value: number + } + scriptsig: string + scriptsig_asm: string + witness: string[] + is_coinbase: boolean + sequence: number +} + +export interface VoutObject { + scriptpubkey: string + scriptpubkey_asm: string + scriptpubkey_type: string + scriptpubkey_address: string + value: number +} + +export interface TransactionData { + txid: string + version: number + locktime: number + vin: VinObject[] + vout: VoutObject[] + size: number + weight: number + fee: number + status: { + confirmed: boolean + block_height: number + block_hash: string + block_time: number + } +} export class Transaction implements TransactionInterface { /** @@ -13,6 +57,11 @@ export class Transaction implements TransactionInterface { */ provider: Provider + /** + * Transaction data + */ + data: TransactionData | null = null + /** * @param {string} id Transaction id * @param {Provider} provider Blockchain network provider @@ -25,15 +74,46 @@ export class Transaction implements TransactionInterface { /** * @returns {Promise} Transaction data */ - async getData(): Promise { - return {} + async getData(): Promise { + if (this.data !== null) { + return this.data + } + try { + const data = (await axios.get(this.provider.createEndpoint('tx/' + this.id))).data + + if (data?.txid !== this.id) { + this.data = null + } + + return (this.data = data as TransactionData) + } catch (error) { + throw new Error(ErrorTypeEnum.RPC_REQUEST_ERROR) + } } /** - * @returns {Promise} Wait for the transaction to be confirmed + * @param {number} ms - Milliseconds to wait for the transaction to be confirmed. Default is 4000ms + * @returns {Promise} Status of the transaction */ - async wait(): Promise { - return await Promise.resolve(TransactionStatusEnum.CONFIRMED) + async wait(ms: number = 4000): Promise { + return await new Promise((resolve, reject) => { + const check = async (): Promise => { + try { + const status = await this.getStatus() + if (status === TransactionStatusEnum.CONFIRMED) { + resolve(TransactionStatusEnum.CONFIRMED) + return + } else if (status === TransactionStatusEnum.FAILED) { + reject(TransactionStatusEnum.FAILED) + return + } + setTimeout(check, ms) + } catch (error) { + reject(TransactionStatusEnum.FAILED) + } + } + void check() + }) } /** @@ -47,48 +127,67 @@ export class Transaction implements TransactionInterface { * @returns {string} Transaction URL */ getUrl(): string { - return 'example' + return this.provider.explorer + 'tx/' + this.id } /** * @returns {Promise} Wallet address of the sender of transaction */ async getSigner(): Promise { - return 'example' + const data = await this.getData() + return data?.vin[0].prevout.scriptpubkey_address ?? '' } /** * @returns {Promise} Transaction fee */ async getFee(): Promise { - return 0 + const data = await this.getData() + return fromSatoshi(data?.fee ?? 0) } /** * @returns {Promise} Block number that transaction */ async getBlockNumber(): Promise { - return 0 + const data = await this.getData() + return data?.status?.block_height ?? 0 } /** * @returns {Promise} Block timestamp that transaction */ async getBlockTimestamp(): Promise { - return 0 + const data = await this.getData() + return data?.status?.block_time ?? 0 } /** * @returns {Promise} Confirmation count of the block */ async getBlockConfirmationCount(): Promise { - return 0 + const data = await this.getData() + if (data === null) { + return 0 + } + const latestBlock = await axios.get(this.provider.createEndpoint('blocks/tip/height')) + return (latestBlock.data as number) - data?.status?.block_height } /** * @returns {Promise} Status of the transaction */ async getStatus(): Promise { - return TransactionStatusEnum.CONFIRMED + const data = await this.getData() + if (data === null) { + return TransactionStatusEnum.PENDING + } else if (data.status?.block_height !== undefined) { + if (data.status.confirmed) { + return TransactionStatusEnum.CONFIRMED + } else { + return TransactionStatusEnum.FAILED + } + } + return TransactionStatusEnum.PENDING } } diff --git a/packages/networks/bitcoin/src/services/Provider.ts b/packages/networks/bitcoin/src/services/Provider.ts index 93da6f3..994ac64 100644 --- a/packages/networks/bitcoin/src/services/Provider.ts +++ b/packages/networks/bitcoin/src/services/Provider.ts @@ -75,7 +75,7 @@ export class Provider implements Omit { */ async checkRpcConnection(url?: string): Promise { try { - const response = await axios.get(url ?? this.api + 'block-height/0') + const response = await axios.get(url ?? this.createEndpoint('blocks/tip/height')) if (response.status !== 200) { return new Error(response.statusText + ': ' + JSON.stringify(response.data)) diff --git a/packages/networks/bitcoin/src/services/TransactionSigner.ts b/packages/networks/bitcoin/src/services/TransactionSigner.ts index 7f2356d..07987d8 100644 --- a/packages/networks/bitcoin/src/services/TransactionSigner.ts +++ b/packages/networks/bitcoin/src/services/TransactionSigner.ts @@ -54,7 +54,7 @@ export class TransactionSigner implements TransactionSignerInterface { url: `https://blockstream.info/testnet/api/tx`, data: this.signedData }) - return new Transaction(result.data.txid as string) + return new Transaction(result.data as string) } catch (error: any) { throw new Error(JSON.stringify((error as AxiosError).response?.data)) } diff --git a/packages/networks/bitcoin/src/utils.ts b/packages/networks/bitcoin/src/utils.ts new file mode 100644 index 0000000..1b2a5d2 --- /dev/null +++ b/packages/networks/bitcoin/src/utils.ts @@ -0,0 +1,11 @@ +import { math } from '@multiplechain/utils' + +export * from '@multiplechain/utils' + +export const fromSatoshi = (amount: number): number => { + return math.div(amount, 100000000, 8) +} + +export const toSatoshi = (amount: number): number => { + return math.mul(amount, 100000000) +} diff --git a/packages/networks/bitcoin/tests/models.spec.ts b/packages/networks/bitcoin/tests/models.spec.ts index 34c5579..d4265de 100644 --- a/packages/networks/bitcoin/tests/models.spec.ts +++ b/packages/networks/bitcoin/tests/models.spec.ts @@ -1,7 +1,78 @@ import { describe, it, expect } from 'vitest' +import { Transaction } from '../src/models/Transaction.ts' +import { CoinTransaction } from '../src/models/CoinTransaction.ts' +import { AssetDirectionEnum, TransactionStatusEnum } from '@multiplechain/types' -describe('example', () => { - it('should work', () => { - expect(1 + 1).toBe(2) +const testAmount = Number(process.env.BTC_TRANSFER_AMOUNT) +const senderTestAddress = String(process.env.BTC_SENDER_ADDRESS) +const receiverTestAddress = String(process.env.BTC_RECEIVER_ADDRESS) +const txId = '335c8a251e5f18121977c3159f46983d5943325abccc19e4718c49089553d60c' + +describe('Transaction', () => { + const tx = new Transaction(txId) + it('Id', async () => { + expect(tx.getId()).toBe(txId) + }) + + it('Data', async () => { + expect(await tx.getData()).toBeTypeOf('object') + }) + + it('Wait', async () => { + expect(await tx.wait()).toBe(TransactionStatusEnum.CONFIRMED) + }) + + it('URL', async () => { + expect(tx.getUrl()).toBe('https://blockstream.info/testnet/tx/' + txId) + }) + + it('Sender', async () => { + expect((await tx.getSigner()).toLowerCase()).toBe(senderTestAddress.toLowerCase()) + }) + + it('Fee', async () => { + expect(await tx.getFee()).toBe(0.00014) + }) + + it('Block Number', async () => { + expect(await tx.getBlockNumber()).toBe(2814543) + }) + + it('Block Timestamp', async () => { + expect(await tx.getBlockTimestamp()).toBe(1715328679) + }) + + it('Block Confirmation Count', async () => { + expect(await tx.getBlockConfirmationCount()).toBeGreaterThan(13) + }) + + it('Status', async () => { + expect(await tx.getStatus()).toBe(TransactionStatusEnum.CONFIRMED) + }) +}) + +describe('Coin Transaction', () => { + const tx = new CoinTransaction(txId) + + it('Receiver', async () => { + expect((await tx.getReceiver()).toLowerCase()).toBe(receiverTestAddress.toLowerCase()) + }) + + it('Amount', async () => { + expect(await tx.getAmount()).toBe(testAmount) + }) + + it('Verify Transfer', async () => { + expect( + await tx.verifyTransfer(AssetDirectionEnum.INCOMING, receiverTestAddress, testAmount) + ).toBe(TransactionStatusEnum.CONFIRMED) + + expect( + await tx.verifyTransfer(AssetDirectionEnum.OUTGOING, senderTestAddress, testAmount) + ).toBe(TransactionStatusEnum.CONFIRMED) + + expect( + await tx.verifyTransfer(AssetDirectionEnum.OUTGOING, receiverTestAddress, testAmount) + ).toBe(TransactionStatusEnum.FAILED) }) }) diff --git a/packages/networks/bitcoin/vitest.config.ts b/packages/networks/bitcoin/vitest.config.ts index 73ee32b..c96edcb 100644 --- a/packages/networks/bitcoin/vitest.config.ts +++ b/packages/networks/bitcoin/vitest.config.ts @@ -5,6 +5,7 @@ export default mergeConfig( mainConfig, defineConfig({ test: { + testTimeout: 600000, setupFiles: ['./tests/setup.ts'] } }) From 0af37824fa0d27dcf8fe32e5f5a0bda18b133d5d Mon Sep 17 00:00:00 2001 From: Halil Beycan <50718965+BeycanDeveloper@users.noreply.github.com> Date: Fri, 10 May 2024 17:48:31 +0800 Subject: [PATCH 13/90] updated --- .../networks/boilerplate/src/services/TransactionListener.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/networks/boilerplate/src/services/TransactionListener.ts b/packages/networks/boilerplate/src/services/TransactionListener.ts index 47ee7d8..da72fc3 100644 --- a/packages/networks/boilerplate/src/services/TransactionListener.ts +++ b/packages/networks/boilerplate/src/services/TransactionListener.ts @@ -25,7 +25,7 @@ export class TransactionListener /** * Transaction listener filter */ - filter?: DynamicTransactionListenerFilterType + filter?: DynamicTransactionListenerFilterType | Record /** * Provider @@ -49,7 +49,7 @@ export class TransactionListener */ constructor(type: T, filter?: DynamicTransactionListenerFilterType, provider?: Provider) { this.type = type - this.filter = filter + this.filter = filter ?? {} this.provider = provider ?? Provider.instance } From 00dfa029444fad22ab2b531dedc4fdd83362f719 Mon Sep 17 00:00:00 2001 From: Halil Beycan <50718965+BeycanDeveloper@users.noreply.github.com> Date: Fri, 10 May 2024 21:26:11 +0800 Subject: [PATCH 14/90] completed listener --- packages/networks/bitcoin/package-lock.json | 277 +++++++++++++++++- packages/networks/bitcoin/package.json | 3 +- .../networks/bitcoin/src/services/Provider.ts | 7 +- .../src/services/TransactionListener.ts | 197 ++++++++++++- packages/networks/bitcoin/src/utils.ts | 2 +- .../networks/bitcoin/tests/services.spec.ts | 36 +++ 6 files changed, 512 insertions(+), 10 deletions(-) diff --git a/packages/networks/bitcoin/package-lock.json b/packages/networks/bitcoin/package-lock.json index 61bed1b..312fc86 100644 --- a/packages/networks/bitcoin/package-lock.json +++ b/packages/networks/bitcoin/package-lock.json @@ -10,7 +10,13 @@ "license": "MIT", "dependencies": { "@multiplechain/types": "^0.1.55", - "@multiplechain/utils": "^0.1.18" + "@multiplechain/utils": "^0.1.18", + "axios": "^1.6.8", + "bitcore-lib": "^10.0.28", + "ws": "^8.17.0" + }, + "devDependencies": { + "@types/bitcore-lib": "^0.15.6" } }, "node_modules/@multiplechain/types": { @@ -84,6 +90,15 @@ "url": "https://paulmillr.com/funding/" } }, + "node_modules/@types/bitcore-lib": { + "version": "0.15.6", + "resolved": "https://registry.npmjs.org/@types/bitcore-lib/-/bitcore-lib-0.15.6.tgz", + "integrity": "sha512-CtKDBgSBubPXZ0wFeCiUCSdzH+cuy6nFya3FboOqf44evi+OmkQPqEg3ASMpmPDYE8vkcxV302Iu8lZqCjYieg==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@types/node": { "version": "20.12.11", "resolved": "https://registry.npmjs.org/@types/node/-/node-20.12.11.tgz", @@ -100,6 +115,11 @@ "@types/node": "*" } }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" + }, "node_modules/available-typed-arrays": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", @@ -114,6 +134,34 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/axios": { + "version": "1.6.8", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.8.tgz", + "integrity": "sha512-v/ZHtJDU39mDpyBoFVkETcd/uNdxrWRrg3bKpOKzXFA6Bvqopts6ALSMU3y6ijYxbw2B+wPrIv46egTzJXCLGQ==", + "dependencies": { + "follow-redirects": "^1.15.6", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" + } + }, + "node_modules/base-x": { + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/base-x/-/base-x-3.0.9.tgz", + "integrity": "sha512-H7JU6iBHTal1gp56aKoaa//YUxEaAOUiydvrV/pILqIHXTtqxSkATOnDA2u+jZ/61sD+L/412+7kzXRtWukhpQ==", + "dependencies": { + "safe-buffer": "^5.0.1" + } + }, + "node_modules/bech32": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/bech32/-/bech32-2.0.0.tgz", + "integrity": "sha512-LcknSilhIGatDAsY1ak2I8VtGaHNhgMSYVxFrGLXv+xLHytaKZKcaUJJUE7qmBr7h33o5YQwP55pMI0xmkpJwg==" + }, + "node_modules/bigi": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/bigi/-/bigi-1.4.2.tgz", + "integrity": "sha512-ddkU+dFIuEIW8lE7ZwdIAf2UPoM90eaprg5m3YXAVVTmKlqV/9BX4A2M8BOK2yOq6/VgZFVhK6QAxJebhlbhzw==" + }, "node_modules/bignumber.js": { "version": "9.1.2", "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.1.2.tgz", @@ -122,6 +170,64 @@ "node": "*" } }, + "node_modules/bip-schnorr": { + "version": "0.6.4", + "resolved": "https://registry.npmjs.org/bip-schnorr/-/bip-schnorr-0.6.4.tgz", + "integrity": "sha512-dNKw7Lea8B0wMIN4OjEmOk/Z5qUGqoPDY0P2QttLqGk1hmDPytLWW8PR5Pb6Vxy6CprcdEgfJpOjUu+ONQveyg==", + "dependencies": { + "bigi": "^1.4.2", + "ecurve": "^1.0.6", + "js-sha256": "^0.9.0", + "randombytes": "^2.1.0", + "safe-buffer": "^5.2.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/bitcore-lib": { + "version": "10.0.28", + "resolved": "https://registry.npmjs.org/bitcore-lib/-/bitcore-lib-10.0.28.tgz", + "integrity": "sha512-uOWHpWbUxEj411p+tp6DCb9NfZdsCAHl6Z/rs96mquQMsef29fOqWUyk4Bl7yLf+KwzU5ZKy0HIPnjGFlmpXpg==", + "dependencies": { + "bech32": "=2.0.0", + "bip-schnorr": "=0.6.4", + "bn.js": "=4.11.8", + "bs58": "^4.0.1", + "buffer-compare": "=1.1.1", + "elliptic": "^6.5.3", + "inherits": "=2.0.1", + "lodash": "^4.17.20" + } + }, + "node_modules/bitcore-lib/node_modules/inherits": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", + "integrity": "sha512-8nWq2nLTAwd02jTqJExUYFSD/fKq6VH9Y/oG2accc/kdI0V98Bag8d5a4gi3XHz73rDWa2PvTtvcWYquKqSENA==" + }, + "node_modules/bn.js": { + "version": "4.11.8", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz", + "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==" + }, + "node_modules/brorand": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", + "integrity": "sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w==" + }, + "node_modules/bs58": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/bs58/-/bs58-4.0.1.tgz", + "integrity": "sha512-Ok3Wdf5vOIlBrgCvTq96gBkJw+JUEzdBgyaza5HLtPm7yTHkjRy8+JzNyHF7BHa0bNWOQIp3m5YF0nnFcOIKLw==", + "dependencies": { + "base-x": "^3.0.2" + } + }, + "node_modules/buffer-compare": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-compare/-/buffer-compare-1.1.1.tgz", + "integrity": "sha512-O6NvNiHZMd3mlIeMDjP6t/gPG75OqGPeiRZXoMQZJ6iy9GofCls4Ijs5YkPZZwoysizLiedhticmdyx/GyHghA==" + }, "node_modules/call-bind": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", @@ -140,6 +246,17 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, "node_modules/define-data-property": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", @@ -156,6 +273,42 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/ecurve": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/ecurve/-/ecurve-1.0.6.tgz", + "integrity": "sha512-/BzEjNfiSuB7jIWKcS/z8FK9jNjmEWvUV2YZ4RLSmcDtP7Lq0m6FvDuSnJpBlDpGRpfRQeTLGLBI8H+kEv0r+w==", + "dependencies": { + "bigi": "^1.1.0", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/elliptic": { + "version": "6.5.5", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.5.tgz", + "integrity": "sha512-7EjbcmUm17NQFu4Pmgmq2olYMj8nwMnpcddByChSUjArp8F5DQWcIcpriwO4ZToLNAJig0yiyjswfyGNje/ixw==", + "dependencies": { + "bn.js": "^4.11.9", + "brorand": "^1.1.0", + "hash.js": "^1.0.0", + "hmac-drbg": "^1.0.1", + "inherits": "^2.0.4", + "minimalistic-assert": "^1.0.1", + "minimalistic-crypto-utils": "^1.0.1" + } + }, + "node_modules/elliptic/node_modules/bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" + }, "node_modules/es-define-property": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", @@ -191,6 +344,25 @@ "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz", "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==" }, + "node_modules/follow-redirects": { + "version": "1.15.6", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz", + "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, "node_modules/for-each": { "version": "0.3.3", "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", @@ -199,6 +371,19 @@ "is-callable": "^1.1.3" } }, + "node_modules/form-data": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/function-bind": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", @@ -283,6 +468,15 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/hash.js": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz", + "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==", + "dependencies": { + "inherits": "^2.0.3", + "minimalistic-assert": "^1.0.1" + } + }, "node_modules/hasown": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", @@ -294,6 +488,16 @@ "node": ">= 0.4" } }, + "node_modules/hmac-drbg": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", + "integrity": "sha512-Tti3gMqLdZfhOQY1Mzf/AanLiqh1WTiJgEj26ZuYQ9fbkLomzGchCws4FyrSd4VkpBfiNhaE1On+lOz894jvXg==", + "dependencies": { + "hash.js": "^1.0.3", + "minimalistic-assert": "^1.0.0", + "minimalistic-crypto-utils": "^1.0.1" + } + }, "node_modules/inherits": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", @@ -353,6 +557,45 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/js-sha256": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/js-sha256/-/js-sha256-0.9.0.tgz", + "integrity": "sha512-sga3MHh9sgQN2+pJ9VYZ+1LPwXOxuBJBA5nrR5/ofPfuiJBE2hnjsaN8se8JznOmGLN2p49Pe5U/ttafcs/apA==" + }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/minimalistic-assert": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", + "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==" + }, + "node_modules/minimalistic-crypto-utils": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", + "integrity": "sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg==" + }, "node_modules/possible-typed-array-names": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz", @@ -361,6 +604,38 @@ "node": ">= 0.4" } }, + "node_modules/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" + }, + "node_modules/randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "dependencies": { + "safe-buffer": "^5.1.0" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, "node_modules/set-function-length": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", diff --git a/packages/networks/bitcoin/package.json b/packages/networks/bitcoin/package.json index 965358e..d313e6a 100644 --- a/packages/networks/bitcoin/package.json +++ b/packages/networks/bitcoin/package.json @@ -65,7 +65,8 @@ "@multiplechain/types": "^0.1.55", "@multiplechain/utils": "^0.1.18", "axios": "^1.6.8", - "bitcore-lib": "^10.0.28" + "bitcore-lib": "^10.0.28", + "ws": "^8.17.0" }, "devDependencies": { "@types/bitcore-lib": "^0.15.6" diff --git a/packages/networks/bitcoin/src/services/Provider.ts b/packages/networks/bitcoin/src/services/Provider.ts index 994ac64..30086e2 100644 --- a/packages/networks/bitcoin/src/services/Provider.ts +++ b/packages/networks/bitcoin/src/services/Provider.ts @@ -33,6 +33,11 @@ export class Provider implements Omit { */ blockCypherToken?: string + /** + * Default BlockCypher token + */ + defaultBlockCypherToken = '49d43a59a4f24d31a9731eb067ab971c' + /** * Static instance of the provider */ @@ -117,7 +122,7 @@ export class Provider implements Omit { if (this.network.testnet) { this.api = 'https://blockstream.info/testnet/api/' this.explorer = 'https://blockstream.info/testnet/' - const token = this.network.blockCypherToken ?? '49d43a59a4f24d31a9731eb067ab971c' + const token = this.network.blockCypherToken ?? this.defaultBlockCypherToken this.wsUrl = 'wss://socket.blockcypher.com/v1/btc/test3?token=' + token } else { this.api = 'https://blockstream.info/api/' diff --git a/packages/networks/bitcoin/src/services/TransactionListener.ts b/packages/networks/bitcoin/src/services/TransactionListener.ts index d680d46..83227b2 100644 --- a/packages/networks/bitcoin/src/services/TransactionListener.ts +++ b/packages/networks/bitcoin/src/services/TransactionListener.ts @@ -5,9 +5,20 @@ import type { TransactionListenerCallbackType, DynamicTransactionListenerFilterType } from '@multiplechain/types' - +import WebSocket from 'ws' import { Provider } from './Provider.ts' import { TransactionListenerProcessIndex } from '@multiplechain/types' +import { checkWebSocket, objectsEqual } from '@multiplechain/utils' +import { CoinTransaction } from '../models/CoinTransaction.ts' +import { Transaction } from '../models/Transaction.ts' +import { fromSatoshi } from '../utils.ts' + +interface Values { + txId: string + amount?: number + sender?: string + receiver?: string +} export class TransactionListener implements TransactionListenerInterface @@ -25,7 +36,7 @@ export class TransactionListener /** * Transaction listener filter */ - filter?: DynamicTransactionListenerFilterType + filter?: DynamicTransactionListenerFilterType | Record /** * Provider @@ -42,6 +53,16 @@ export class TransactionListener */ triggeredTransactions: string[] = [] + /** + * WebSocket + */ + webSocket: WebSocket + + /** + * Dynamic stop method + */ + dynamicStop: () => void = () => {} + /** * @param {T} type - Transaction type * @param {DynamicTransactionListenerFilterType} filter - Transaction listener filter @@ -49,7 +70,7 @@ export class TransactionListener */ constructor(type: T, filter?: DynamicTransactionListenerFilterType, provider?: Provider) { this.type = type - this.filter = filter + this.filter = filter ?? {} this.provider = provider ?? Provider.instance } @@ -60,7 +81,7 @@ export class TransactionListener stop(): void { if (this.status) { this.status = false - // stop the listener + this.dynamicStop() } } @@ -90,7 +111,21 @@ export class TransactionListener * @returns {Promise} */ async on(callback: TransactionListenerCallbackType): Promise { + if (this.webSocket === undefined) { + try { + await checkWebSocket(this.provider.wsUrl) + this.webSocket = new WebSocket(this.provider.wsUrl) + } catch (error) { + throw new Error( + 'WebSocket connection is not available' + + (error instanceof Error ? ': ' + error.message : '') + ) + } + } + + this.start() this.callbacks.push(callback) + return true } @@ -108,12 +143,102 @@ export class TransactionListener } } + isBlockCypherProcess(): boolean { + return this.provider.isTestnet() || this.provider.blockCypherToken !== undefined + } + + /** + * Create message for the listener + * @param {string} receiver - Receiver address + * @returns {string} Message + */ + createMessage(receiver?: string): string { + let message + if (this.isBlockCypherProcess()) { + interface Config { + event: string + token: string + address?: string + } + + const config: Config = { + event: 'unconfirmed-tx', + token: this.provider.blockCypherToken ?? this.provider.defaultBlockCypherToken + } + + if (receiver !== undefined) { + config.address = receiver + } + + message = JSON.stringify(config) + } else { + message = JSON.stringify({ + op: 'unconfirmed_sub' + }) + } + + this.dynamicStop = () => { + if (!this.isBlockCypherProcess()) { + this.webSocket.send( + JSON.stringify({ + op: 'unconfirmed_unsub' + }) + ) + } + this.webSocket.close() + } + + return message + } + + /** + * Parse the data + * @param {any} data - Data + * @returns {Values} Parsed data + */ + getValues(data: any): Values { + const values: Values = { + txId: '' + } + + if (this.isBlockCypherProcess()) { + values.txId = data.hash + values.sender = data.inputs[0].addresses[0] + values.receiver = data.outputs[0].addresses[0] + values.amount = fromSatoshi(data.outputs[0].value as number) + } else { + values.txId = data.x.hash + values.receiver = data.x.out[0].addr + values.sender = data.x.inputs[0].prev_out.addr + values.amount = fromSatoshi(data.x.out[0].value as number) + } + + return values + } + /** * General transaction process * @returns {void} */ generalProcess(): void { - // General transaction process + const message = this.createMessage() + + this.webSocket.addEventListener('open', () => { + this.webSocket.send(message) + }) + + this.webSocket.addEventListener('message', async (res) => { + const values = this.getValues(JSON.parse(res.data as string)) + + if ( + this.filter?.signer !== undefined && + values.sender !== this.filter.signer.toLowerCase() + ) { + return + } + + this.trigger(new Transaction(values.txId)) + }) } /** @@ -129,7 +254,67 @@ export class TransactionListener * @returns {void} */ coinProcess(): void { - // Coin transaction process + const filter = this.filter as DynamicTransactionListenerFilterType + + if ( + filter.signer !== undefined && + filter.sender !== undefined && + filter.signer !== filter.sender + ) { + throw new Error( + 'Sender and signer must be the same in coin transactions. Or only one of them can be defined.' + ) + } + + const sender = filter.sender ?? filter.signer + + const message = this.createMessage(filter.receiver) + + this.webSocket.addEventListener('open', () => { + this.webSocket.send(message) + }) + + this.webSocket.addEventListener('message', async (res) => { + const data = JSON.parse(res.data as string) + + interface ParamsType { + sender?: string + receiver?: string + } + + const expectedParams: ParamsType = {} + const receivedParams: ParamsType = {} + + if (String(data.event).includes('events limit reached')) { + throw new Error('BlockCypher events limit reached.') + } + + const values = this.getValues(data) + + console.log(values) + + if (sender !== undefined) { + expectedParams.sender = sender.toLowerCase() + receivedParams.sender = values.sender?.toLowerCase() + } + + if (filter.receiver !== undefined) { + expectedParams.receiver = filter.receiver.toLowerCase() + receivedParams.receiver = values.receiver?.toLowerCase() + } + + if (!objectsEqual(expectedParams, receivedParams)) { + return + } + + const transaction = new CoinTransaction(values.txId) + + if (filter.amount !== undefined && values.amount !== filter.amount) { + return + } + + this.trigger(transaction) + }) } /** diff --git a/packages/networks/bitcoin/src/utils.ts b/packages/networks/bitcoin/src/utils.ts index 1b2a5d2..14bd3ec 100644 --- a/packages/networks/bitcoin/src/utils.ts +++ b/packages/networks/bitcoin/src/utils.ts @@ -7,5 +7,5 @@ export const fromSatoshi = (amount: number): number => { } export const toSatoshi = (amount: number): number => { - return math.mul(amount, 100000000) + return math.mul(amount, 100000000, 8) } diff --git a/packages/networks/bitcoin/tests/services.spec.ts b/packages/networks/bitcoin/tests/services.spec.ts index 37d09f4..e01ff25 100644 --- a/packages/networks/bitcoin/tests/services.spec.ts +++ b/packages/networks/bitcoin/tests/services.spec.ts @@ -2,6 +2,15 @@ import { describe, it, expect } from 'vitest' import { provider } from './setup.ts' import { Provider } from '../src/services/Provider.ts' +import { TransactionListener } from '../src/services/TransactionListener.ts' +import { TransactionTypeEnum } from '@multiplechain/types' +import { CoinTransaction } from '../src/models/CoinTransaction.ts' +import { Coin } from '../src/assets/Coin.ts' + +const senderTestAddress = String(process.env.BTC_SENDER_ADDRESS) +const receiverTestAddress = String(process.env.BTC_RECEIVER_ADDRESS) +const senderPrivateKey = String(process.env.BTC_SENDER_PRIVATE_KEY) +const listenerTestIsActive = Boolean(process.env.BTC_LISTENER_TEST_IS_ACTIVE !== 'false') describe('Provider', () => { it('isTestnet', () => { @@ -20,3 +29,30 @@ describe('Provider', () => { expect(await provider.checkWsConnection()).toBe(true) }) }) + +describe('Transaction Listener', () => { + if (!listenerTestIsActive) { + it('No test is active', () => { + expect(true).toBe(true) + }) + return + } + + it('Coin', async () => { + const listener = new TransactionListener(TransactionTypeEnum.COIN, { + signer: senderTestAddress, + receiver: receiverTestAddress + }) + + void listener.on((transaction) => { + listener.stop() + expect(transaction).toBeInstanceOf(CoinTransaction) + }) + + const signer = await new Coin().transfer(senderTestAddress, receiverTestAddress, 0.0001) + + const transaction = await (await signer.sign(senderPrivateKey)).send() + + expect(transaction).toBeInstanceOf(CoinTransaction) + }) +}) From 6048ee80ed6078196b893dd1a2d5028d517fba90 Mon Sep 17 00:00:00 2001 From: Halil Beycan <50718965+BeycanDeveloper@users.noreply.github.com> Date: Fri, 10 May 2024 21:26:55 +0800 Subject: [PATCH 15/90] updated --- packages/networks/boilerplate/src/browser/Wallet.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/networks/boilerplate/src/browser/Wallet.ts b/packages/networks/boilerplate/src/browser/Wallet.ts index 652d8a1..83ade3f 100644 --- a/packages/networks/boilerplate/src/browser/Wallet.ts +++ b/packages/networks/boilerplate/src/browser/Wallet.ts @@ -5,7 +5,7 @@ import type { TransactionSignerInterface, ProviderInterface } from '@multiplechain/types' -import { Provider } from '../services/Provider' +import { Provider } from '../services/Provider.ts' export class Wallet implements WalletInterface { adapter: WalletAdapterInterface From 98630ffc42eec6ecade53560d00aa3218959fc21 Mon Sep 17 00:00:00 2001 From: Halil Beycan <50718965+BeycanDeveloper@users.noreply.github.com> Date: Fri, 10 May 2024 21:27:44 +0800 Subject: [PATCH 16/90] updated --- packages/networks/bitcoin/src/browser/Wallet.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/networks/bitcoin/src/browser/Wallet.ts b/packages/networks/bitcoin/src/browser/Wallet.ts index 652d8a1..83ade3f 100644 --- a/packages/networks/bitcoin/src/browser/Wallet.ts +++ b/packages/networks/bitcoin/src/browser/Wallet.ts @@ -5,7 +5,7 @@ import type { TransactionSignerInterface, ProviderInterface } from '@multiplechain/types' -import { Provider } from '../services/Provider' +import { Provider } from '../services/Provider.ts' export class Wallet implements WalletInterface { adapter: WalletAdapterInterface From 75ec00e2ae82ac60d721c1d0ad9665bc84b8840f Mon Sep 17 00:00:00 2001 From: Halil Beycan <50718965+BeycanDeveloper@users.noreply.github.com> Date: Fri, 10 May 2024 21:28:00 +0800 Subject: [PATCH 17/90] updated --- packages/networks/boilerplate/src/browser/adapters/Example.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/networks/boilerplate/src/browser/adapters/Example.ts b/packages/networks/boilerplate/src/browser/adapters/Example.ts index 79ecd67..b7390b3 100644 --- a/packages/networks/boilerplate/src/browser/adapters/Example.ts +++ b/packages/networks/boilerplate/src/browser/adapters/Example.ts @@ -12,7 +12,7 @@ const Example: WalletAdapterInterface = { name: 'Example', icon: 'icon base64 string here', platforms: [WalletPlatformEnum.BROWSER, WalletPlatformEnum.MOBILE], - downloadLink: 'wallet download link here', + downloadLink: 'wallet download link here', createDeepLink(url: string, ops?: object): string { return `https://example.com/dapp/${url}` }, From a6da18b6f6a3039572953cdb0da05ceee433db69 Mon Sep 17 00:00:00 2001 From: Halil Beycan <50718965+BeycanDeveloper@users.noreply.github.com> Date: Fri, 10 May 2024 22:16:04 +0800 Subject: [PATCH 18/90] configured for wallet and adapters --- packages/networks/bitcoin/index.html | 23 +------ packages/networks/bitcoin/src/assets/Coin.ts | 7 +- .../networks/bitcoin/src/browser/Wallet.ts | 66 +++++++++++++++---- .../bitcoin/src/browser/adapters/Example.ts | 29 -------- .../bitcoin/src/browser/adapters/UniSat.ts | 60 +++++++++++++++++ .../bitcoin/src/browser/adapters/icons.ts | 3 + .../bitcoin/src/browser/adapters/index.ts | 2 +- .../bitcoin/src/services/TransactionSigner.ts | 13 +++- 8 files changed, 135 insertions(+), 68 deletions(-) delete mode 100644 packages/networks/bitcoin/src/browser/adapters/Example.ts create mode 100644 packages/networks/bitcoin/src/browser/adapters/UniSat.ts create mode 100644 packages/networks/bitcoin/src/browser/adapters/icons.ts diff --git a/packages/networks/bitcoin/index.html b/packages/networks/bitcoin/index.html index 7ace16d..7a0c989 100644 --- a/packages/networks/bitcoin/index.html +++ b/packages/networks/bitcoin/index.html @@ -187,9 +187,6 @@
Deep link:
-
- Chain id: -
Connected address:
@@ -205,12 +202,6 @@
Result:
- -
- Result: -
+ + \ No newline at end of file diff --git a/packages/networks/solana/package.json b/packages/networks/solana/package.json new file mode 100644 index 0000000..4759d62 --- /dev/null +++ b/packages/networks/solana/package.json @@ -0,0 +1,68 @@ +{ + "name": "@multiplechain/solana", + "version": "0.1.0", + "type": "module", + "main": "dist/index.cjs", + "module": "dist/index.es.js", + "unpkg": "dist/index.umd.js", + "browser": "dist/index.umd.js", + "jsdelivr": "dist/index.umd.js", + "exports": { + ".": { + "import": { + "default": "./dist/index.es.js", + "types": "./dist/browser/index.d.ts" + }, + "require": { + "default": "./dist/index.cjs", + "types": "./dist/index.d.ts" + } + }, + "./node": { + "default": "./dist/index.cjs", + "types": "./dist/index.d.ts" + }, + "./browser": { + "default": "./dist/index.es.js", + "types": "./dist/browser/index.d.ts" + } + }, + "files": [ + "dist", + "README.md", + "!tsconfig.tsbuildinfo" + ], + "scripts": { + "dev": "vite", + "clean": "rm -rf dist", + "watch": "tsc --watch", + "build:vite": "vite build", + "build:node": "tsx esbuild.ts", + "typecheck": "tsc --noEmit", + "lint": "eslint . --ext .ts", + "test": "vitest run --dir tests", + "test-ui": "vitest watch --ui", + "prepublishOnly": "pnpm run build", + "build": "pnpm run build:vite && pnpm run build:node" + }, + "keywords": [ + "web3", + "crypto", + "blockchain", + "multiple-chain" + ], + "author": "MultipleChain", + "license": "MIT", + "homepage": "https://github.com/MultipleChain/js/tree/master/packages/networks/network-name", + "repository": { + "type": "git", + "url": "git+https://github.com/MultipleChain/js.git" + }, + "bugs": { + "url": "https://github.com/MultipleChain/js/issues" + }, + "dependencies": { + "@multiplechain/types": "^0.1.55", + "@multiplechain/utils": "^0.1.18" + } +} \ No newline at end of file diff --git a/packages/networks/solana/pnpm-lock.yaml b/packages/networks/solana/pnpm-lock.yaml new file mode 100644 index 0000000..aae81e5 --- /dev/null +++ b/packages/networks/solana/pnpm-lock.yaml @@ -0,0 +1,310 @@ +lockfileVersion: '6.0' + +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false + +dependencies: + '@multiplechain/types': + specifier: ^0.1.55 + version: 0.1.55 + '@multiplechain/utils': + specifier: ^0.1.18 + version: 0.1.18 + +packages: + + /@multiplechain/types@0.1.55: + resolution: {integrity: sha512-9fYrLaDxX2pj9zfIbmvk1hPF3FH/bK+Q3uTF+k3zdsitP/HzQ1S9zImNz20Tvoqkk1ns+/8ecE0Y6GNowsDOQA==} + dev: false + + /@multiplechain/utils@0.1.18: + resolution: {integrity: sha512-UCoOOBJrawp/lInepxuoEiYwId0wMPg7rX8p78FLqzGl8f/b93sAtv7sP87/VVKwhdoEuNZ/uQjckycmNeks/w==} + dependencies: + '@types/ws': 8.5.10 + bignumber.js: 9.1.2 + web3-utils: 4.2.1 + ws: 8.16.0 + transitivePeerDependencies: + - bufferutil + - utf-8-validate + dev: false + + /@noble/curves@1.3.0: + resolution: {integrity: sha512-t01iSXPuN+Eqzb4eBX0S5oubSqXbK/xXa1Ne18Hj8f9pStxztHCE2gfboSp/dZRLSqfuLpRK2nDXDK+W9puocA==} + dependencies: + '@noble/hashes': 1.3.3 + dev: false + + /@noble/hashes@1.3.3: + resolution: {integrity: sha512-V7/fPHgl+jsVPXqqeOzT8egNj2iBIVt+ECeMMG8TdcnTikP3oaBtUVqpT/gYCR68aEBJSF+XbYUxStjbFMqIIA==} + engines: {node: '>= 16'} + dev: false + + /@scure/base@1.1.6: + resolution: {integrity: sha512-ok9AWwhcgYuGG3Zfhyqg+zwl+Wn5uE+dwC0NV/2qQkx4dABbb/bx96vWu8NSj+BNjjSjno+JRYRjle1jV08k3g==} + dev: false + + /@scure/bip32@1.3.3: + resolution: {integrity: sha512-LJaN3HwRbfQK0X1xFSi0Q9amqOgzQnnDngIt+ZlsBC3Bm7/nE7K0kwshZHyaru79yIVRv/e1mQAjZyuZG6jOFQ==} + dependencies: + '@noble/curves': 1.3.0 + '@noble/hashes': 1.3.3 + '@scure/base': 1.1.6 + dev: false + + /@scure/bip39@1.2.2: + resolution: {integrity: sha512-HYf9TUXG80beW+hGAt3TRM8wU6pQoYur9iNypTROm42dorCGmLnFe3eWjz3gOq6G62H2WRh0FCzAR1PI+29zIA==} + dependencies: + '@noble/hashes': 1.3.3 + '@scure/base': 1.1.6 + dev: false + + /@types/node@20.12.7: + resolution: {integrity: sha512-wq0cICSkRLVaf3UGLMGItu/PtdY7oaXaI/RVU+xliKVOtRna3PRY57ZDfztpDL0n11vfymMUnXv8QwYCO7L1wg==} + dependencies: + undici-types: 5.26.5 + dev: false + + /@types/ws@8.5.10: + resolution: {integrity: sha512-vmQSUcfalpIq0R9q7uTo2lXs6eGIpt9wtnLdMv9LVpIjCA/+ufZRozlVoVelIYixx1ugCBKDhn89vnsEGOCx9A==} + dependencies: + '@types/node': 20.12.7 + dev: false + + /available-typed-arrays@1.0.7: + resolution: {integrity: sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==} + engines: {node: '>= 0.4'} + dependencies: + possible-typed-array-names: 1.0.0 + dev: false + + /bignumber.js@9.1.2: + resolution: {integrity: sha512-2/mKyZH9K85bzOEfhXDBFZTGd1CTs+5IHpeFQo9luiBG7hghdC851Pj2WAhb6E3R6b9tZj/XKhbg4fum+Kepug==} + dev: false + + /call-bind@1.0.7: + resolution: {integrity: sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==} + engines: {node: '>= 0.4'} + dependencies: + es-define-property: 1.0.0 + es-errors: 1.3.0 + function-bind: 1.1.2 + get-intrinsic: 1.2.4 + set-function-length: 1.2.2 + dev: false + + /define-data-property@1.1.4: + resolution: {integrity: sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==} + engines: {node: '>= 0.4'} + dependencies: + es-define-property: 1.0.0 + es-errors: 1.3.0 + gopd: 1.0.1 + dev: false + + /es-define-property@1.0.0: + resolution: {integrity: sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==} + engines: {node: '>= 0.4'} + dependencies: + get-intrinsic: 1.2.4 + dev: false + + /es-errors@1.3.0: + resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==} + engines: {node: '>= 0.4'} + dev: false + + /ethereum-cryptography@2.1.3: + resolution: {integrity: sha512-BlwbIL7/P45W8FGW2r7LGuvoEZ+7PWsniMvQ4p5s2xCyw9tmaDlpfsN9HjAucbF+t/qpVHwZUisgfK24TCW8aA==} + dependencies: + '@noble/curves': 1.3.0 + '@noble/hashes': 1.3.3 + '@scure/bip32': 1.3.3 + '@scure/bip39': 1.2.2 + dev: false + + /eventemitter3@5.0.1: + resolution: {integrity: sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==} + dev: false + + /for-each@0.3.3: + resolution: {integrity: sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==} + dependencies: + is-callable: 1.2.7 + dev: false + + /function-bind@1.1.2: + resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} + dev: false + + /get-intrinsic@1.2.4: + resolution: {integrity: sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==} + engines: {node: '>= 0.4'} + dependencies: + es-errors: 1.3.0 + function-bind: 1.1.2 + has-proto: 1.0.3 + has-symbols: 1.0.3 + hasown: 2.0.2 + dev: false + + /gopd@1.0.1: + resolution: {integrity: sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==} + dependencies: + get-intrinsic: 1.2.4 + dev: false + + /has-property-descriptors@1.0.2: + resolution: {integrity: sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==} + dependencies: + es-define-property: 1.0.0 + dev: false + + /has-proto@1.0.3: + resolution: {integrity: sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==} + engines: {node: '>= 0.4'} + dev: false + + /has-symbols@1.0.3: + resolution: {integrity: sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==} + engines: {node: '>= 0.4'} + dev: false + + /has-tostringtag@1.0.2: + resolution: {integrity: sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==} + engines: {node: '>= 0.4'} + dependencies: + has-symbols: 1.0.3 + dev: false + + /hasown@2.0.2: + resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} + engines: {node: '>= 0.4'} + dependencies: + function-bind: 1.1.2 + dev: false + + /inherits@2.0.4: + resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} + dev: false + + /is-arguments@1.1.1: + resolution: {integrity: sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.7 + has-tostringtag: 1.0.2 + dev: false + + /is-callable@1.2.7: + resolution: {integrity: sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==} + engines: {node: '>= 0.4'} + dev: false + + /is-generator-function@1.0.10: + resolution: {integrity: sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==} + engines: {node: '>= 0.4'} + dependencies: + has-tostringtag: 1.0.2 + dev: false + + /is-typed-array@1.1.13: + resolution: {integrity: sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw==} + engines: {node: '>= 0.4'} + dependencies: + which-typed-array: 1.1.15 + dev: false + + /possible-typed-array-names@1.0.0: + resolution: {integrity: sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==} + engines: {node: '>= 0.4'} + dev: false + + /set-function-length@1.2.2: + resolution: {integrity: sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==} + engines: {node: '>= 0.4'} + dependencies: + define-data-property: 1.1.4 + es-errors: 1.3.0 + function-bind: 1.1.2 + get-intrinsic: 1.2.4 + gopd: 1.0.1 + has-property-descriptors: 1.0.2 + dev: false + + /undici-types@5.26.5: + resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==} + dev: false + + /util@0.12.5: + resolution: {integrity: sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA==} + dependencies: + inherits: 2.0.4 + is-arguments: 1.1.1 + is-generator-function: 1.0.10 + is-typed-array: 1.1.13 + which-typed-array: 1.1.15 + dev: false + + /web3-errors@1.1.4: + resolution: {integrity: sha512-WahtszSqILez+83AxGecVroyZsMuuRT+KmQp4Si5P4Rnqbczno1k748PCrZTS1J4UCPmXMG2/Vt+0Bz2zwXkwQ==} + engines: {node: '>=14', npm: '>=6.12.0'} + dependencies: + web3-types: 1.5.0 + dev: false + + /web3-types@1.5.0: + resolution: {integrity: sha512-geWuMIeegQ8AedKAO6wO4G4j1gyQ1F/AyKLMw2vud4bsfZayyzWJgCMDZtjYMm5uo2a7i8j1W3/4QFmzlSy5cw==} + engines: {node: '>=14', npm: '>=6.12.0'} + dev: false + + /web3-utils@4.2.1: + resolution: {integrity: sha512-Fk29BlEqD9Q9Cnw4pBkKw7czcXiRpsSco/BzEUl4ye0ZTSHANQFfjsfQmNm4t7uY11u6Ah+8F3tNjBeU4CA80A==} + engines: {node: '>=14', npm: '>=6.12.0'} + dependencies: + ethereum-cryptography: 2.1.3 + eventemitter3: 5.0.1 + web3-errors: 1.1.4 + web3-types: 1.5.0 + web3-validator: 2.0.4 + dev: false + + /web3-validator@2.0.4: + resolution: {integrity: sha512-qRxVePwdW+SByOmTpDZFWHIUAa7PswvxNszrOua6BoGqAhERo5oJZBN+EbWtK/+O+ApNxt5FR3nCPmiZldiOQA==} + engines: {node: '>=14', npm: '>=6.12.0'} + dependencies: + ethereum-cryptography: 2.1.3 + util: 0.12.5 + web3-errors: 1.1.4 + web3-types: 1.5.0 + zod: 3.22.4 + dev: false + + /which-typed-array@1.1.15: + resolution: {integrity: sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA==} + engines: {node: '>= 0.4'} + dependencies: + available-typed-arrays: 1.0.7 + call-bind: 1.0.7 + for-each: 0.3.3 + gopd: 1.0.1 + has-tostringtag: 1.0.2 + dev: false + + /ws@8.16.0: + resolution: {integrity: sha512-HS0c//TP7Ina87TfiPUz1rQzMhHrl/SG2guqRcTOIUYD2q8uhUdNHZYJUaQ8aTGPzCh+c6oawMKW35nFl1dxyQ==} + engines: {node: '>=10.0.0'} + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: '>=5.0.2' + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + dev: false + + /zod@3.22.4: + resolution: {integrity: sha512-iC+8Io04lddc+mVqQ9AZ7OQ2MrUKGN+oIQyq1vemgt46jwCwLfhq7/pwnBnNXXXZb8VTVLKwp9EDkx+ryxIWmg==} + dev: false diff --git a/packages/networks/solana/src/assets/Coin.ts b/packages/networks/solana/src/assets/Coin.ts new file mode 100644 index 0000000..1c2d8b3 --- /dev/null +++ b/packages/networks/solana/src/assets/Coin.ts @@ -0,0 +1,60 @@ +import { Provider } from '../services/Provider.ts' +import type { CoinInterface } from '@multiplechain/types' +import { CoinTransactionSigner } from '../services/TransactionSigner.ts' + +export class Coin implements CoinInterface { + /** + * Blockchain network provider + */ + provider: Provider + + /** + * @param {Provider} provider network provider + */ + constructor(provider?: Provider) { + this.provider = provider ?? Provider.instance + } + + /** + * @returns {string} Coin name + */ + getName(): string { + return 'example' + } + + /** + * @returns {string} Coin symbol + */ + getSymbol(): string { + return 'example' + } + + /** + * @returns {number} Decimal value of the coin + */ + getDecimals(): number { + return 18 + } + + /** + * @param {string} owner Wallet address + * @returns {Promise} Wallet balance as currency of COIN + */ + async getBalance(owner: string): Promise { + return 0 + } + + /** + * @param {string} sender Sender wallet address + * @param {string} receiver Receiver wallet address + * @param {number} amount Amount of assets that will be transferred + * @returns {Promise} Transaction signer + */ + async transfer( + sender: string, + receiver: string, + amount: number + ): Promise { + return new CoinTransactionSigner('example') + } +} diff --git a/packages/networks/solana/src/assets/Contract.ts b/packages/networks/solana/src/assets/Contract.ts new file mode 100644 index 0000000..ee3a295 --- /dev/null +++ b/packages/networks/solana/src/assets/Contract.ts @@ -0,0 +1,58 @@ +import { Provider } from '../services/Provider.ts' +import type { ContractInterface } from '@multiplechain/types' + +export class Contract implements ContractInterface { + /** + * Contract address + */ + address: string + + /** + * Blockchain network provider + */ + provider: Provider + + /** + * @param {string} address Contract address + * @param {Provider} provider Blockchain network provider + */ + constructor(address: string, provider?: Provider) { + this.address = address + this.provider = provider ?? Provider.instance + } + + /** + * @returns {string} Contract address + */ + getAddress(): string { + return this.address + } + + /** + * @param {string} method Method name + * @param {any[]} args Method parameters + * @returns {Promise} Method result + */ + async callMethod(method: string, ...args: any[]): Promise { + return {} + } + + /** + * @param {string} method Method name + * @param {any[]} args Sender wallet address + * @returns {Promise} Encoded method data + */ + async getMethodData(method: string, ...args: any[]): Promise { + return {} + } + + /** + * @param {string} method Method name + * @param {string} from Sender wallet address + * @param {any[]} args Method parameters + * @returns {Promise} Encoded method data + */ + async createTransactionData(method: string, from: string, ...args: any[]): Promise { + return '' + } +} diff --git a/packages/networks/solana/src/assets/NFT.ts b/packages/networks/solana/src/assets/NFT.ts new file mode 100644 index 0000000..0a89a51 --- /dev/null +++ b/packages/networks/solana/src/assets/NFT.ts @@ -0,0 +1,96 @@ +import { Contract } from './Contract.ts' +import type { NftInterface } from '@multiplechain/types' +import { NftTransactionSigner } from '../services/TransactionSigner.ts' + +export class NFT extends Contract implements NftInterface { + /** + * @returns {Promise} NFT name + */ + async getName(): Promise { + return 'example' + } + + /** + * @returns {Promise} NFT symbol + */ + async getSymbol(): Promise { + return 'example' + } + + /** + * @param {string} owner Wallet address + * @returns {Promise} Wallet balance as currency of NFT + */ + async getBalance(owner: string): Promise { + return 0 + } + + /** + * @param {number | string} nftId NFT ID + * @returns {Promise} Wallet address of the owner of the NFT + */ + async getOwner(nftId: number | string): Promise { + return 'example' + } + + /** + * @param {number | string} nftId NFT ID + * @returns {Promise} URI of the NFT + */ + async getTokenURI(nftId: number | string): Promise { + return 'example' + } + + /** + * @param {number | string} nftId ID of the NFT that will be transferred + * @returns {Promise} Wallet address of the approved spender + */ + async getApproved(nftId: number | string): Promise { + return 'example' + } + + /** + * @param {string} sender Sender address + * @param {string} receiver Receiver address + * @param {number | string} nftId NFT ID + * @returns {Promise} Transaction signer + */ + async transfer( + sender: string, + receiver: string, + nftId: number | string + ): Promise { + return new NftTransactionSigner('example') + } + + /** + * @param {string} spender Spender address + * @param {string} owner Owner address + * @param {string} receiver Receiver address + * @param {number | string} nftId NFT ID + * @returns {Promise} Transaction signer + */ + async transferFrom( + spender: string, + owner: string, + receiver: string, + nftId: number | string + ): Promise { + return new NftTransactionSigner('example') + } + + /** + * Gives permission to the spender to spend owner's tokens + * @param {string} owner Address of owner of the tokens that will be used + * @param {string} spender Address of the spender that will use the tokens of owner + * @param {number | string} nftId ID of the NFT that will be transferred + * @returns {Promise} Transaction signer + */ + async approve( + owner: string, + spender: string, + nftId: number | string + ): Promise { + return new NftTransactionSigner('example') + } +} diff --git a/packages/networks/solana/src/assets/Token.ts b/packages/networks/solana/src/assets/Token.ts new file mode 100644 index 0000000..8d30a0d --- /dev/null +++ b/packages/networks/solana/src/assets/Token.ts @@ -0,0 +1,96 @@ +import { Contract } from './Contract.ts' +import type { TokenInterface } from '@multiplechain/types' +import { TokenTransactionSigner } from '../services/TransactionSigner.ts' + +export class Token extends Contract implements TokenInterface { + /** + * @returns {Promise} Token name + */ + async getName(): Promise { + return 'example' + } + + /** + * @returns {Promise} Token symbol + */ + async getSymbol(): Promise { + return 'example' + } + + /** + * @returns {Promise} Decimal value of the token + */ + async getDecimals(): Promise { + return 18 + } + + /** + * @param {string} owner Wallet address + * @returns {Promise} Wallet balance as currency of TOKEN + */ + async getBalance(owner: string): Promise { + return 0 + } + + /** + * @returns {Promise} Total supply of the token + */ + async getTotalSupply(): Promise { + return 0 + } + + /** + * @param {string} owner Address of owner of the tokens that is being used + * @param {string} spender Address of the spender that is using the tokens of owner + * @returns {Promise} Amount of tokens that the spender is allowed to spend + */ + async getAllowance(owner: string, spender: string): Promise { + return 0 + } + + /** + * transfer() method is the main method for processing transfers for fungible assets (TOKEN, COIN) + * @param {string} sender Sender wallet address + * @param {string} receiver Receiver wallet address + * @param {number} amount Amount of assets that will be transferred + * @returns {Promise} Transaction signer + */ + async transfer( + sender: string, + receiver: string, + amount: number + ): Promise { + return new TokenTransactionSigner('example') + } + + /** + * @param {string} spender Address of the spender of transaction + * @param {string} owner Sender wallet address + * @param {string} receiver Receiver wallet address + * @param {number} amount Amount of tokens that will be transferred + * @returns {Promise} Transaction signer + */ + async transferFrom( + spender: string, + owner: string, + receiver: string, + amount: number + ): Promise { + return new TokenTransactionSigner('example') + } + + /** + * Gives permission to the spender to spend owner's tokens + * @param {string} owner Address of owner of the tokens that will be used + * @param {string} spender Address of the spender that will use the tokens of owner + * @param {number} amount Amount of the tokens that will be used + * @returns {Promise} Transaction signer + */ + async approve( + owner: string, + spender: string, + amount: number + ): Promise { + return new TokenTransactionSigner('example') + } +} diff --git a/packages/networks/solana/src/assets/index.ts b/packages/networks/solana/src/assets/index.ts new file mode 100644 index 0000000..7ea522f --- /dev/null +++ b/packages/networks/solana/src/assets/index.ts @@ -0,0 +1,4 @@ +export * from './NFT.ts' +export * from './Coin.ts' +export * from './Token.ts' +export * from './Contract.ts' diff --git a/packages/networks/solana/src/browser/Wallet.ts b/packages/networks/solana/src/browser/Wallet.ts new file mode 100644 index 0000000..83ade3f --- /dev/null +++ b/packages/networks/solana/src/browser/Wallet.ts @@ -0,0 +1,128 @@ +import type { + WalletInterface, + WalletAdapterInterface, + WalletPlatformEnum, + TransactionSignerInterface, + ProviderInterface +} from '@multiplechain/types' +import { Provider } from '../services/Provider.ts' + +export class Wallet implements WalletInterface { + adapter: WalletAdapterInterface + + walletProvider: object + + networkProvider: Provider + + /** + * @param {WalletAdapterInterface} adapter + * @param {Provider} provider + */ + constructor(adapter: WalletAdapterInterface, provider?: Provider) { + this.adapter = adapter + this.networkProvider = provider ?? Provider.instance + } + + /** + * @returns {string} + */ + getId(): string { + return this.adapter.id + } + + /** + * @returns {string} + */ + getName(): string { + return this.adapter.name + } + + /** + * @returns {string} + */ + getIcon(): string { + return this.adapter.icon + } + + /** + * @returns {WalletPlatformEnum[]} + */ + getPlatforms(): WalletPlatformEnum[] { + return this.adapter.platforms + } + + /** + * @returns {string} + */ + getDownloadLink(): string | undefined { + return this.adapter.downloadLink + } + + /** + * @param {string} url + * @param {object} ops + * @returns {string} + */ + createDeepLink(url: string, ops?: object): string | null { + if (this.adapter.createDeepLink === undefined) { + return null + } + + return this.adapter.createDeepLink(url, ops) + } + + /** + * @param {ProviderInterface} provider + * @param {Object} ops + * @returns {Promise} + */ + async connect(provider?: ProviderInterface, ops?: object): Promise { + await this.adapter.connect() + return 'wallet address' + } + + /** + * @returns {boolean} + */ + async isDetected(): Promise { + return await this.adapter.isDetected() + } + + /** + * @returns {boolean} + */ + async isConnected(): Promise { + return await this.adapter.isConnected() + } + + /** + * @returns {Promise} + */ + async getAddress(): Promise { + return 'wallet address' + } + + /** + * @param {string} message + */ + async signMessage(message: string): Promise { + return 'signed message' + } + + /** + * @param {TransactionSignerInterface} transactionSigner + * @returns {Promise} + */ + async sendTransaction(transactionSigner: TransactionSignerInterface): Promise { + return 'transaction hash' + } + + /** + * @param {string} eventName + * @param {Function} callback + * @returns {void} + */ + on(eventName: string, callback: (...args: any[]) => void): void { + 'wallet events' + } +} diff --git a/packages/networks/solana/src/browser/adapters/Example.ts b/packages/networks/solana/src/browser/adapters/Example.ts new file mode 100644 index 0000000..b7390b3 --- /dev/null +++ b/packages/networks/solana/src/browser/adapters/Example.ts @@ -0,0 +1,29 @@ +import { WalletPlatformEnum } from '@multiplechain/types' +import type { WalletAdapterInterface } from '@multiplechain/types' + +declare global { + interface Window { + example: any + } +} + +const Example: WalletAdapterInterface = { + id: 'example', + name: 'Example', + icon: 'icon base64 string here', + platforms: [WalletPlatformEnum.BROWSER, WalletPlatformEnum.MOBILE], + downloadLink: 'wallet download link here', + createDeepLink(url: string, ops?: object): string { + return `https://example.com/dapp/${url}` + }, + isDetected: () => Boolean(window?.example), + isConnected: async () => { + return true // return true if connected + }, + connect: async () => { + // connect wallet here + return window.example + } +} + +export default Example diff --git a/packages/networks/solana/src/browser/adapters/index.ts b/packages/networks/solana/src/browser/adapters/index.ts new file mode 100644 index 0000000..de0149d --- /dev/null +++ b/packages/networks/solana/src/browser/adapters/index.ts @@ -0,0 +1 @@ +export { default as Example } from './Example.ts' diff --git a/packages/networks/solana/src/browser/index.ts b/packages/networks/solana/src/browser/index.ts new file mode 100644 index 0000000..787e9bd --- /dev/null +++ b/packages/networks/solana/src/browser/index.ts @@ -0,0 +1,25 @@ +import { Wallet } from './Wallet.ts' +import * as adapterList from './adapters/index.ts' +import type { + WalletAdapterListType, + WalletAdapterInterface, + RegisterWalletAdapterType +} from '@multiplechain/types' + +const adapters: WalletAdapterListType = {} + +const registerAdapter: RegisterWalletAdapterType = (adapter: WalletAdapterInterface): void => { + if (Object.values(adapters).find((a) => a.id === adapter.id) !== undefined) { + throw new Error(`Adapter with id ${adapter.id} already exists`) + } + + adapters[adapter.id] = adapter +} + +export * from '../index.ts' + +export const browser = { + Wallet, + registerAdapter, + adapters: Object.assign(adapters, adapterList) +} diff --git a/packages/networks/solana/src/index.ts b/packages/networks/solana/src/index.ts new file mode 100644 index 0000000..668ab52 --- /dev/null +++ b/packages/networks/solana/src/index.ts @@ -0,0 +1,8 @@ +export * from './services/Provider.ts' + +export * as assets from './assets/index.ts' +export * as models from './models/index.ts' +export * as services from './services/index.ts' + +export * as utils from '@multiplechain/utils' +export * as types from '@multiplechain/types' diff --git a/packages/networks/solana/src/models/CoinTransaction.ts b/packages/networks/solana/src/models/CoinTransaction.ts new file mode 100644 index 0000000..9857f2e --- /dev/null +++ b/packages/networks/solana/src/models/CoinTransaction.ts @@ -0,0 +1,40 @@ +import { Transaction } from './Transaction.ts' +import { TransactionStatusEnum } from '@multiplechain/types' +import type { AssetDirectionEnum, CoinTransactionInterface } from '@multiplechain/types' + +export class CoinTransaction extends Transaction implements CoinTransactionInterface { + /** + * @returns {Promise} Wallet address of the receiver of transaction + */ + async getReceiver(): Promise { + return 'example' + } + + /** + * @returns {Promise} Wallet address of the sender of transaction + */ + async getSender(): Promise { + return 'example' + } + + /** + * @returns {Promise} Amount of coin that will be transferred + */ + async getAmount(): Promise { + return 0 + } + + /** + * @param {AssetDirectionEnum} direction - Direction of the transaction (asset) + * @param {string} address - Wallet address of the receiver or sender of the transaction, dependant on direction + * @param {number} amount Amount of assets that will be transferred + * @returns {Promise} Status of the transaction + */ + async verifyTransfer( + direction: AssetDirectionEnum, + address: string, + amount: number + ): Promise { + return TransactionStatusEnum.PENDING + } +} diff --git a/packages/networks/solana/src/models/ContractTransaction.ts b/packages/networks/solana/src/models/ContractTransaction.ts new file mode 100644 index 0000000..ad57241 --- /dev/null +++ b/packages/networks/solana/src/models/ContractTransaction.ts @@ -0,0 +1,11 @@ +import { Transaction } from './Transaction.ts' +import type { ContractTransactionInterface } from '@multiplechain/types' + +export class ContractTransaction extends Transaction implements ContractTransactionInterface { + /** + * @returns {Promise} Contract address of the transaction + */ + async getAddress(): Promise { + return 'example' + } +} diff --git a/packages/networks/solana/src/models/NftTransaction.ts b/packages/networks/solana/src/models/NftTransaction.ts new file mode 100644 index 0000000..09b8d80 --- /dev/null +++ b/packages/networks/solana/src/models/NftTransaction.ts @@ -0,0 +1,41 @@ +import { ContractTransaction } from './ContractTransaction.ts' +import { TransactionStatusEnum } from '@multiplechain/types' +import type { NftTransactionInterface, AssetDirectionEnum } from '@multiplechain/types' + +export class NftTransaction extends ContractTransaction implements NftTransactionInterface { + /** + * @returns {Promise} Receiver wallet address + */ + async getReceiver(): Promise { + return 'example' + } + + /** + * @returns {Promise} Wallet address of the sender of transaction + */ + async getSender(): Promise { + return 'example' + } + + /** + * @returns {Promise} NFT ID + */ + async getNftId(): Promise { + return 0 + } + + /** + * @param {AssetDirectionEnum} direction - Direction of the transaction (nft) + * @param {string} address - Wallet address of the receiver or sender of the transaction, dependant on direction + * @param {number} nftId ID of the NFT that will be transferred + * @override verifyTransfer() in AssetTransactionInterface + * @returns {Promise} Status of the transaction + */ + async verifyTransfer( + direction: AssetDirectionEnum, + address: string, + nftId: number | string + ): Promise { + return TransactionStatusEnum.PENDING + } +} diff --git a/packages/networks/solana/src/models/TokenTransaction.ts b/packages/networks/solana/src/models/TokenTransaction.ts new file mode 100644 index 0000000..b1ea29e --- /dev/null +++ b/packages/networks/solana/src/models/TokenTransaction.ts @@ -0,0 +1,40 @@ +import { ContractTransaction } from './ContractTransaction.ts' +import { TransactionStatusEnum } from '@multiplechain/types' +import type { AssetDirectionEnum, TokenTransactionInterface } from '@multiplechain/types' + +export class TokenTransaction extends ContractTransaction implements TokenTransactionInterface { + /** + * @returns {Promise} Wallet address of the receiver of transaction + */ + async getReceiver(): Promise { + return 'example' + } + + /** + * @returns {Promise} Wallet address of the sender of transaction + */ + async getSender(): Promise { + return 'example' + } + + /** + * @returns {Promise} Amount of tokens that will be transferred + */ + async getAmount(): Promise { + return 0 + } + + /** + * @param {AssetDirectionEnum} direction - Direction of the transaction (token) + * @param {string} address - Wallet address of the owner or spender of the transaction, dependant on direction + * @param {number} amount Amount of tokens that will be approved + * @returns {Promise} Status of the transaction + */ + async verifyTransfer( + direction: AssetDirectionEnum, + address: string, + amount: number + ): Promise { + return TransactionStatusEnum.PENDING + } +} diff --git a/packages/networks/solana/src/models/Transaction.ts b/packages/networks/solana/src/models/Transaction.ts new file mode 100644 index 0000000..15f111d --- /dev/null +++ b/packages/networks/solana/src/models/Transaction.ts @@ -0,0 +1,94 @@ +import { Provider } from '../services/Provider.ts' +import type { TransactionInterface } from '@multiplechain/types' +import { TransactionStatusEnum } from '@multiplechain/types' + +export class Transaction implements TransactionInterface { + /** + * Each transaction has its own unique ID defined by the user + */ + id: string + + /** + * Blockchain network provider + */ + provider: Provider + + /** + * @param {string} id Transaction id + * @param {Provider} provider Blockchain network provider + */ + constructor(id: string, provider?: Provider) { + this.id = id + this.provider = provider ?? Provider.instance + } + + /** + * @returns {Promise} Transaction data + */ + async getData(): Promise { + return {} + } + + /** + * @returns {Promise} Wait for the transaction to be confirmed + */ + async wait(): Promise { + return await Promise.resolve(TransactionStatusEnum.CONFIRMED) + } + + /** + * @returns {string} Transaction ID + */ + getId(): string { + return this.id + } + + /** + * @returns {string} Transaction URL + */ + getUrl(): string { + return 'example' + } + + /** + * @returns {Promise} Wallet address of the sender of transaction + */ + async getSigner(): Promise { + return 'example' + } + + /** + * @returns {Promise} Transaction fee + */ + async getFee(): Promise { + return 0 + } + + /** + * @returns {Promise} Block number that transaction + */ + async getBlockNumber(): Promise { + return 0 + } + + /** + * @returns {Promise} Block timestamp that transaction + */ + async getBlockTimestamp(): Promise { + return 0 + } + + /** + * @returns {Promise} Confirmation count of the block + */ + async getBlockConfirmationCount(): Promise { + return 0 + } + + /** + * @returns {Promise} Status of the transaction + */ + async getStatus(): Promise { + return TransactionStatusEnum.CONFIRMED + } +} diff --git a/packages/networks/solana/src/models/index.ts b/packages/networks/solana/src/models/index.ts new file mode 100644 index 0000000..cc0a27c --- /dev/null +++ b/packages/networks/solana/src/models/index.ts @@ -0,0 +1,5 @@ +export * from './Transaction.ts' +export * from './NftTransaction.ts' +export * from './CoinTransaction.ts' +export * from './TokenTransaction.ts' +export * from './ContractTransaction.ts' diff --git a/packages/networks/solana/src/services/Provider.ts b/packages/networks/solana/src/services/Provider.ts new file mode 100644 index 0000000..d92d40d --- /dev/null +++ b/packages/networks/solana/src/services/Provider.ts @@ -0,0 +1,82 @@ +import { + ErrorTypeEnum, + type NetworkConfigInterface, + type ProviderInterface +} from '@multiplechain/types' + +export class Provider implements ProviderInterface { + /** + * Network configuration of the provider + */ + network: NetworkConfigInterface + + /** + * Static instance of the provider + */ + private static _instance: Provider + + /** + * @param network - Network configuration of the provider + */ + constructor(network: NetworkConfigInterface) { + this.update(network) + } + + /** + * Get the static instance of the provider + * @returns {Provider} Provider + */ + static get instance(): Provider { + if (Provider._instance === undefined) { + throw new Error(ErrorTypeEnum.PROVIDER_IS_NOT_INITIALIZED) + } + return Provider._instance + } + + /** + * Initialize the static instance of the provider + * @param {NetworkConfigInterface} network - Network configuration of the provider + * @returns {void} + */ + static initialize(network: NetworkConfigInterface): void { + if (Provider._instance !== undefined) { + throw new Error(ErrorTypeEnum.PROVIDER_IS_ALREADY_INITIALIZED) + } + Provider._instance = new Provider(network) + } + + /** + * Check RPC connection + * @param {string} url - RPC URL + * @returns {Promise} + */ + async checkRpcConnection(url?: string): Promise { + return true + } + + /** + * Check WS connection + * @param {string} url - Websocket URL + * @returns {Promise} + */ + async checkWsConnection(url?: string): Promise { + return true + } + + /** + * Update network configuration of the provider + * @param network - Network configuration of the provider + */ + update(network: NetworkConfigInterface): void { + this.network = network + Provider._instance = this + } + + /** + * Get the current network configuration is testnet or not + * @returns boolean + */ + isTestnet(): boolean { + return this.network?.testnet ?? false + } +} diff --git a/packages/networks/solana/src/services/TransactionListener.ts b/packages/networks/solana/src/services/TransactionListener.ts new file mode 100644 index 0000000..da72fc3 --- /dev/null +++ b/packages/networks/solana/src/services/TransactionListener.ts @@ -0,0 +1,150 @@ +import type { + TransactionTypeEnum, + DynamicTransactionType, + TransactionListenerInterface, + TransactionListenerCallbackType, + DynamicTransactionListenerFilterType +} from '@multiplechain/types' + +import { Provider } from './Provider.ts' +import { TransactionListenerProcessIndex } from '@multiplechain/types' + +export class TransactionListener + implements TransactionListenerInterface +{ + /** + * Transaction type + */ + type: T + + /** + * Transaction listener callback + */ + callbacks: TransactionListenerCallbackType[] = [] + + /** + * Transaction listener filter + */ + filter?: DynamicTransactionListenerFilterType | Record + + /** + * Provider + */ + provider: Provider + + /** + * Listener status + */ + status: boolean = false + + /** + * Triggered transactions + */ + triggeredTransactions: string[] = [] + + /** + * @param {T} type - Transaction type + * @param {DynamicTransactionListenerFilterType} filter - Transaction listener filter + * @param {Provider} provider - Provider + */ + constructor(type: T, filter?: DynamicTransactionListenerFilterType, provider?: Provider) { + this.type = type + this.filter = filter ?? {} + this.provider = provider ?? Provider.instance + } + + /** + * Close the listener + * @returns {void} + */ + stop(): void { + if (this.status) { + this.status = false + // stop the listener + } + } + + /** + * Start the listener + * @returns {void} + */ + start(): void { + if (!this.status) { + this.status = true + // @ts-expect-error allow dynamic access + this[TransactionListenerProcessIndex[this.type]]() + } + } + + /** + * Get the listener status + * @returns {boolean} Listener status + */ + getStatus(): boolean { + return this.status + } + + /** + * Listen to the transaction events + * @param {TransactionListenerCallbackType} callback - Transaction listener callback + * @returns {Promise} + */ + async on(callback: TransactionListenerCallbackType): Promise { + this.callbacks.push(callback) + return true + } + + /** + * Trigger the event when a transaction is detected + * @param {DynamicTransactionType} transaction - Transaction data + * @returns {void} + */ + trigger(transaction: DynamicTransactionType): void { + if (!this.triggeredTransactions.includes(transaction.id)) { + this.triggeredTransactions.push(transaction.id) + this.callbacks.forEach((callback) => { + callback(transaction) + }) + } + } + + /** + * General transaction process + * @returns {void} + */ + generalProcess(): void { + // General transaction process + } + + /** + * Contract transaction process + * @returns {void} + */ + contractProcess(): void { + // Contract transaction process + } + + /** + * Coin transaction process + * @returns {void} + */ + coinProcess(): void { + // Coin transaction process + } + + /** + * Token transaction process + * @returns {void} + */ + tokenProcess(): void { + // Token transaction process + } + + /** + * NFT transaction process + * @returns {void} + */ + nftProcess(): void { + // NFT transaction process + } +} diff --git a/packages/networks/solana/src/services/TransactionSigner.ts b/packages/networks/solana/src/services/TransactionSigner.ts new file mode 100644 index 0000000..a76019e --- /dev/null +++ b/packages/networks/solana/src/services/TransactionSigner.ts @@ -0,0 +1,94 @@ +import { Provider } from '../services/Provider.ts' +import { Transaction } from '../models/Transaction.ts' +import { NftTransaction } from '../models/NftTransaction.ts' +import { CoinTransaction } from '../models/CoinTransaction.ts' +import { TokenTransaction } from '../models/TokenTransaction.ts' +import type { TransactionSignerInterface } from '@multiplechain/types' + +export class TransactionSigner implements TransactionSignerInterface { + /** + * Transaction data from the blockchain network + */ + rawData: any + + /** + * Signed transaction data + */ + signedData?: any + + /** + * Blockchain network provider + */ + provider: Provider + + /** + * @param {any} rawData - Transaction data + */ + constructor(rawData: any, provider?: Provider) { + this.rawData = rawData + this.provider = provider ?? Provider.instance + } + + /** + * Sign the transaction + * @param {string} privateKey - Transaction data + * @returns {Promise} Signed transaction data + */ + async sign(privateKey: string): Promise { + return await Promise.resolve(this) + } + + /** + * Send the transaction to the blockchain network + * @returns {Promise} + */ + async send(): Promise { + return await Promise.resolve(new Transaction('example')) + } + + /** + * Get the raw transaction data + * @returns Transaction data + */ + getRawData(): any { + return this.rawData + } + + /** + * Get the signed transaction data + * @returns Signed transaction data + */ + getSignedData(): any { + return this.signedData + } +} + +export class CoinTransactionSigner extends TransactionSigner { + /** + * Send the transaction to the blockchain network + * @returns {Promise} Transaction data + */ + async send(): Promise { + return new CoinTransaction((await super.send()).getId()) + } +} + +export class TokenTransactionSigner extends TransactionSigner { + /** + * Send the transaction to the blockchain network + * @returns {Promise} Transaction data + */ + async send(): Promise { + return new TokenTransaction((await super.send()).getId()) + } +} + +export class NftTransactionSigner extends TransactionSigner { + /** + * Send the transaction to the blockchain network + * @returns {Promise} Transaction data + */ + async send(): Promise { + return new NftTransaction((await super.send()).getId()) + } +} diff --git a/packages/networks/solana/src/services/index.ts b/packages/networks/solana/src/services/index.ts new file mode 100644 index 0000000..549a382 --- /dev/null +++ b/packages/networks/solana/src/services/index.ts @@ -0,0 +1,2 @@ +export * from './TransactionSigner.ts' +export * from './TransactionListener.ts' diff --git a/packages/networks/solana/tests/assets.spec.ts b/packages/networks/solana/tests/assets.spec.ts new file mode 100644 index 0000000..34c5579 --- /dev/null +++ b/packages/networks/solana/tests/assets.spec.ts @@ -0,0 +1,7 @@ +import { describe, it, expect } from 'vitest' + +describe('example', () => { + it('should work', () => { + expect(1 + 1).toBe(2) + }) +}) diff --git a/packages/networks/solana/tests/models.spec.ts b/packages/networks/solana/tests/models.spec.ts new file mode 100644 index 0000000..34c5579 --- /dev/null +++ b/packages/networks/solana/tests/models.spec.ts @@ -0,0 +1,7 @@ +import { describe, it, expect } from 'vitest' + +describe('example', () => { + it('should work', () => { + expect(1 + 1).toBe(2) + }) +}) diff --git a/packages/networks/solana/tests/services.spec.ts b/packages/networks/solana/tests/services.spec.ts new file mode 100644 index 0000000..34c5579 --- /dev/null +++ b/packages/networks/solana/tests/services.spec.ts @@ -0,0 +1,7 @@ +import { describe, it, expect } from 'vitest' + +describe('example', () => { + it('should work', () => { + expect(1 + 1).toBe(2) + }) +}) diff --git a/packages/networks/solana/tests/setup.ts b/packages/networks/solana/tests/setup.ts new file mode 100644 index 0000000..6c04b6b --- /dev/null +++ b/packages/networks/solana/tests/setup.ts @@ -0,0 +1,13 @@ +import { Provider } from '../src/services/Provider.ts' + +let provider: Provider + +try { + provider = Provider.instance +} catch (e) { + provider = new Provider({ + testnet: true + }) +} + +export { provider } diff --git a/packages/networks/solana/tsconfig.json b/packages/networks/solana/tsconfig.json new file mode 100644 index 0000000..e40c547 --- /dev/null +++ b/packages/networks/solana/tsconfig.json @@ -0,0 +1,21 @@ +{ + "compilerOptions": { + "noEmit": true, + "composite": true, + "declaration": true, + "outDir": "./dist/esm", + "declarationDir": "./dist/types" + }, + "extends": "../../../tsconfig.json", + "include": [ + "src", + ".eslintrc.json", + "tests", + "vite.config.ts", + "esbuild.ts", + "vitest.config.ts", + "../../../esbuild.ts", + "../../../vite.config.ts", + "../../../vitest.config.ts", + ] +} diff --git a/packages/networks/solana/vite.config.ts b/packages/networks/solana/vite.config.ts new file mode 100644 index 0000000..b4b80b7 --- /dev/null +++ b/packages/networks/solana/vite.config.ts @@ -0,0 +1,10 @@ +import { mergeConfig } from 'vite' +import mainConfig from '../../../vite.config.ts' + +export default mergeConfig(mainConfig, { + build: { + lib: { + name: 'Solana' + } + } +}) diff --git a/packages/networks/solana/vite.svg b/packages/networks/solana/vite.svg new file mode 100644 index 0000000..e7b8dfb --- /dev/null +++ b/packages/networks/solana/vite.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/packages/networks/solana/vitest.config.ts b/packages/networks/solana/vitest.config.ts new file mode 100644 index 0000000..73ee32b --- /dev/null +++ b/packages/networks/solana/vitest.config.ts @@ -0,0 +1,11 @@ +import { mergeConfig, defineConfig } from 'vitest/config' +import mainConfig from '../../../vite.config.ts' + +export default mergeConfig( + mainConfig, + defineConfig({ + test: { + setupFiles: ['./tests/setup.ts'] + } + }) +) From 02c023d8a41e7fb0b9a1ff8d8c012989fd570af9 Mon Sep 17 00:00:00 2001 From: Halil Beycan <50718965+BeycanDeveloper@users.noreply.github.com> Date: Thu, 16 May 2024 17:43:03 +0800 Subject: [PATCH 26/90] updated --- packages/networks/boilerplate/vitest.config.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/networks/boilerplate/vitest.config.ts b/packages/networks/boilerplate/vitest.config.ts index 73ee32b..433e719 100644 --- a/packages/networks/boilerplate/vitest.config.ts +++ b/packages/networks/boilerplate/vitest.config.ts @@ -5,6 +5,7 @@ export default mergeConfig( mainConfig, defineConfig({ test: { + testTimeout: 180000, setupFiles: ['./tests/setup.ts'] } }) From e0c3325eec618eb76224c042eb3993afad71c334 Mon Sep 17 00:00:00 2001 From: Halil Beycan <50718965+BeycanDeveloper@users.noreply.github.com> Date: Thu, 16 May 2024 17:51:03 +0800 Subject: [PATCH 27/90] fixed wrong url problem --- packages/networks/evm-chains/src/services/Provider.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/networks/evm-chains/src/services/Provider.ts b/packages/networks/evm-chains/src/services/Provider.ts index 858087e..9431d83 100644 --- a/packages/networks/evm-chains/src/services/Provider.ts +++ b/packages/networks/evm-chains/src/services/Provider.ts @@ -101,7 +101,7 @@ export class Provider implements Omit { */ async checkWsConnection(url?: string): Promise { try { - const result: any = await checkWebSocket(url ?? this.network.rpcUrl) + const result: any = await checkWebSocket(url ?? this.network.wsUrl ?? '') if (result instanceof Error) { return result From d2510c68208f437042f8241fbbeeadfff73037bd Mon Sep 17 00:00:00 2001 From: Halil Beycan <50718965+BeycanDeveloper@users.noreply.github.com> Date: Thu, 16 May 2024 17:51:56 +0800 Subject: [PATCH 28/90] solana is ready for development --- packages/networks/solana/package.json | 6 +- packages/networks/solana/pnpm-lock.yaml | 2533 ++++++++++++++++- .../networks/solana/src/services/Provider.ts | 70 +- .../networks/solana/tests/services.spec.ts | 21 +- packages/networks/solana/tests/setup.ts | 3 +- packages/networks/solana/vitest.config.ts | 1 + vitest.config.ts | 1 + 7 files changed, 2505 insertions(+), 130 deletions(-) diff --git a/packages/networks/solana/package.json b/packages/networks/solana/package.json index 4759d62..d4f28ef 100644 --- a/packages/networks/solana/package.json +++ b/packages/networks/solana/package.json @@ -62,7 +62,11 @@ "url": "https://github.com/MultipleChain/js/issues" }, "dependencies": { + "@metaplex-foundation/js": "^0.20.1", "@multiplechain/types": "^0.1.55", - "@multiplechain/utils": "^0.1.18" + "@multiplechain/utils": "^0.1.18", + "@solana/spl-token": "^0.4.6", + "@solana/web3.js": "^1.91.8", + "axios": "^1.6.8" } } \ No newline at end of file diff --git a/packages/networks/solana/pnpm-lock.yaml b/packages/networks/solana/pnpm-lock.yaml index aae81e5..3789f2e 100644 --- a/packages/networks/solana/pnpm-lock.yaml +++ b/packages/networks/solana/pnpm-lock.yaml @@ -5,15 +5,618 @@ settings: excludeLinksFromLockfile: false dependencies: + '@metaplex-foundation/js': + specifier: ^0.20.1 + version: 0.20.1(arweave@1.15.1)(fastestsmallesttextencoderdecoder@1.0.22) '@multiplechain/types': specifier: ^0.1.55 version: 0.1.55 '@multiplechain/utils': specifier: ^0.1.18 version: 0.1.18 + '@solana/spl-token': + specifier: ^0.4.6 + version: 0.4.6(@solana/web3.js@1.91.8)(fastestsmallesttextencoderdecoder@1.0.22) + '@solana/web3.js': + specifier: ^1.91.8 + version: 1.91.8 + axios: + specifier: ^1.6.8 + version: 1.6.8(debug@4.3.4) packages: + /@babel/runtime@7.24.5: + resolution: {integrity: sha512-Nms86NXrsaeU9vbBJKni6gXiEXZ4CVpYVzEjDH9Sb8vmZ3UljyA1GSOJl/6LGPO8EHLuSF9H+IxNXHPX8QHJ4g==} + engines: {node: '>=6.9.0'} + dependencies: + regenerator-runtime: 0.14.1 + dev: false + + /@ethereumjs/rlp@4.0.1: + resolution: {integrity: sha512-tqsQiBQDQdmPWE1xkkBq4rlSW5QZpLOUJ5RJh2/9fug+q9tnUhuZoVLk7s0scUIKTOzEtR72DFBXI4WiZcMpvw==} + engines: {node: '>=14'} + hasBin: true + dev: false + + /@ethereumjs/util@8.1.0: + resolution: {integrity: sha512-zQ0IqbdX8FZ9aw11vP+dZkKDkS+kgIvQPHnSAXzP9pLu+Rfu3D3XEeLbicvoXJTYnhZiPmsZUxgdzXwNKxRPbA==} + engines: {node: '>=14'} + dependencies: + '@ethereumjs/rlp': 4.0.1 + ethereum-cryptography: 2.1.3 + micro-ftch: 0.3.1 + dev: false + + /@ethersproject/abi@5.7.0: + resolution: {integrity: sha512-351ktp42TiRcYB3H1OP8yajPeAQstMW/yCFokj/AthP9bLHzQFPlOrxOcwYEDkUAICmOHljvN4K39OMTMUa9RA==} + dependencies: + '@ethersproject/address': 5.7.0 + '@ethersproject/bignumber': 5.7.0 + '@ethersproject/bytes': 5.7.0 + '@ethersproject/constants': 5.7.0 + '@ethersproject/hash': 5.7.0 + '@ethersproject/keccak256': 5.7.0 + '@ethersproject/logger': 5.7.0 + '@ethersproject/properties': 5.7.0 + '@ethersproject/strings': 5.7.0 + dev: false + + /@ethersproject/abstract-provider@5.7.0: + resolution: {integrity: sha512-R41c9UkchKCpAqStMYUpdunjo3pkEvZC3FAwZn5S5MGbXoMQOHIdHItezTETxAO5bevtMApSyEhn9+CHcDsWBw==} + dependencies: + '@ethersproject/bignumber': 5.7.0 + '@ethersproject/bytes': 5.7.0 + '@ethersproject/logger': 5.7.0 + '@ethersproject/networks': 5.7.1 + '@ethersproject/properties': 5.7.0 + '@ethersproject/transactions': 5.7.0 + '@ethersproject/web': 5.7.1 + dev: false + + /@ethersproject/abstract-signer@5.7.0: + resolution: {integrity: sha512-a16V8bq1/Cz+TGCkE2OPMTOUDLS3grCpdjoJCYNnVBbdYEMSgKrU0+B90s8b6H+ByYTBZN7a3g76jdIJi7UfKQ==} + dependencies: + '@ethersproject/abstract-provider': 5.7.0 + '@ethersproject/bignumber': 5.7.0 + '@ethersproject/bytes': 5.7.0 + '@ethersproject/logger': 5.7.0 + '@ethersproject/properties': 5.7.0 + dev: false + + /@ethersproject/address@5.7.0: + resolution: {integrity: sha512-9wYhYt7aghVGo758POM5nqcOMaE168Q6aRLJZwUmiqSrAungkG74gSSeKEIR7ukixesdRZGPgVqme6vmxs1fkA==} + dependencies: + '@ethersproject/bignumber': 5.7.0 + '@ethersproject/bytes': 5.7.0 + '@ethersproject/keccak256': 5.7.0 + '@ethersproject/logger': 5.7.0 + '@ethersproject/rlp': 5.7.0 + dev: false + + /@ethersproject/base64@5.7.0: + resolution: {integrity: sha512-Dr8tcHt2mEbsZr/mwTPIQAf3Ai0Bks/7gTw9dSqk1mQvhW3XvRlmDJr/4n+wg1JmCl16NZue17CDh8xb/vZ0sQ==} + dependencies: + '@ethersproject/bytes': 5.7.0 + dev: false + + /@ethersproject/basex@5.7.0: + resolution: {integrity: sha512-ywlh43GwZLv2Voc2gQVTKBoVQ1mti3d8HK5aMxsfu/nRDnMmNqaSJ3r3n85HBByT8OpoY96SXM1FogC533T4zw==} + dependencies: + '@ethersproject/bytes': 5.7.0 + '@ethersproject/properties': 5.7.0 + dev: false + + /@ethersproject/bignumber@5.7.0: + resolution: {integrity: sha512-n1CAdIHRWjSucQO3MC1zPSVgV/6dy/fjL9pMrPP9peL+QxEg9wOsVqwD4+818B6LUEtaXzVHQiuivzRoxPxUGw==} + dependencies: + '@ethersproject/bytes': 5.7.0 + '@ethersproject/logger': 5.7.0 + bn.js: 5.2.1 + dev: false + + /@ethersproject/bytes@5.7.0: + resolution: {integrity: sha512-nsbxwgFXWh9NyYWo+U8atvmMsSdKJprTcICAkvbBffT75qDocbuggBU0SJiVK2MuTrp0q+xvLkTnGMPK1+uA9A==} + dependencies: + '@ethersproject/logger': 5.7.0 + dev: false + + /@ethersproject/constants@5.7.0: + resolution: {integrity: sha512-DHI+y5dBNvkpYUMiRQyxRBYBefZkJfo70VUkUAsRjcPs47muV9evftfZ0PJVCXYbAiCgght0DtcF9srFQmIgWA==} + dependencies: + '@ethersproject/bignumber': 5.7.0 + dev: false + + /@ethersproject/contracts@5.7.0: + resolution: {integrity: sha512-5GJbzEU3X+d33CdfPhcyS+z8MzsTrBGk/sc+G+59+tPa9yFkl6HQ9D6L0QMgNTA9q8dT0XKxxkyp883XsQvbbg==} + dependencies: + '@ethersproject/abi': 5.7.0 + '@ethersproject/abstract-provider': 5.7.0 + '@ethersproject/abstract-signer': 5.7.0 + '@ethersproject/address': 5.7.0 + '@ethersproject/bignumber': 5.7.0 + '@ethersproject/bytes': 5.7.0 + '@ethersproject/constants': 5.7.0 + '@ethersproject/logger': 5.7.0 + '@ethersproject/properties': 5.7.0 + '@ethersproject/transactions': 5.7.0 + dev: false + + /@ethersproject/hash@5.7.0: + resolution: {integrity: sha512-qX5WrQfnah1EFnO5zJv1v46a8HW0+E5xuBBDTwMFZLuVTx0tbU2kkx15NqdjxecrLGatQN9FGQKpb1FKdHCt+g==} + dependencies: + '@ethersproject/abstract-signer': 5.7.0 + '@ethersproject/address': 5.7.0 + '@ethersproject/base64': 5.7.0 + '@ethersproject/bignumber': 5.7.0 + '@ethersproject/bytes': 5.7.0 + '@ethersproject/keccak256': 5.7.0 + '@ethersproject/logger': 5.7.0 + '@ethersproject/properties': 5.7.0 + '@ethersproject/strings': 5.7.0 + dev: false + + /@ethersproject/hdnode@5.7.0: + resolution: {integrity: sha512-OmyYo9EENBPPf4ERhR7oj6uAtUAhYGqOnIS+jE5pTXvdKBS99ikzq1E7Iv0ZQZ5V36Lqx1qZLeak0Ra16qpeOg==} + dependencies: + '@ethersproject/abstract-signer': 5.7.0 + '@ethersproject/basex': 5.7.0 + '@ethersproject/bignumber': 5.7.0 + '@ethersproject/bytes': 5.7.0 + '@ethersproject/logger': 5.7.0 + '@ethersproject/pbkdf2': 5.7.0 + '@ethersproject/properties': 5.7.0 + '@ethersproject/sha2': 5.7.0 + '@ethersproject/signing-key': 5.7.0 + '@ethersproject/strings': 5.7.0 + '@ethersproject/transactions': 5.7.0 + '@ethersproject/wordlists': 5.7.0 + dev: false + + /@ethersproject/json-wallets@5.7.0: + resolution: {integrity: sha512-8oee5Xgu6+RKgJTkvEMl2wDgSPSAQ9MB/3JYjFV9jlKvcYHUXZC+cQp0njgmxdHkYWn8s6/IqIZYm0YWCjO/0g==} + dependencies: + '@ethersproject/abstract-signer': 5.7.0 + '@ethersproject/address': 5.7.0 + '@ethersproject/bytes': 5.7.0 + '@ethersproject/hdnode': 5.7.0 + '@ethersproject/keccak256': 5.7.0 + '@ethersproject/logger': 5.7.0 + '@ethersproject/pbkdf2': 5.7.0 + '@ethersproject/properties': 5.7.0 + '@ethersproject/random': 5.7.0 + '@ethersproject/strings': 5.7.0 + '@ethersproject/transactions': 5.7.0 + aes-js: 3.0.0 + scrypt-js: 3.0.1 + dev: false + + /@ethersproject/keccak256@5.7.0: + resolution: {integrity: sha512-2UcPboeL/iW+pSg6vZ6ydF8tCnv3Iu/8tUmLLzWWGzxWKFFqOBQFLo6uLUv6BDrLgCDfN28RJ/wtByx+jZ4KBg==} + dependencies: + '@ethersproject/bytes': 5.7.0 + js-sha3: 0.8.0 + dev: false + + /@ethersproject/logger@5.7.0: + resolution: {integrity: sha512-0odtFdXu/XHtjQXJYA3u9G0G8btm0ND5Cu8M7i5vhEcE8/HmF4Lbdqanwyv4uQTr2tx6b7fQRmgLrsnpQlmnig==} + dev: false + + /@ethersproject/networks@5.7.1: + resolution: {integrity: sha512-n/MufjFYv3yFcUyfhnXotyDlNdFb7onmkSy8aQERi2PjNcnWQ66xXxa3XlS8nCcA8aJKJjIIMNJTC7tu80GwpQ==} + dependencies: + '@ethersproject/logger': 5.7.0 + dev: false + + /@ethersproject/pbkdf2@5.7.0: + resolution: {integrity: sha512-oR/dBRZR6GTyaofd86DehG72hY6NpAjhabkhxgr3X2FpJtJuodEl2auADWBZfhDHgVCbu3/H/Ocq2uC6dpNjjw==} + dependencies: + '@ethersproject/bytes': 5.7.0 + '@ethersproject/sha2': 5.7.0 + dev: false + + /@ethersproject/properties@5.7.0: + resolution: {integrity: sha512-J87jy8suntrAkIZtecpxEPxY//szqr1mlBaYlQ0r4RCaiD2hjheqF9s1LVE8vVuJCXisjIP+JgtK/Do54ej4Sw==} + dependencies: + '@ethersproject/logger': 5.7.0 + dev: false + + /@ethersproject/providers@5.7.2: + resolution: {integrity: sha512-g34EWZ1WWAVgr4aptGlVBF8mhl3VWjv+8hoAnzStu8Ah22VHBsuGzP17eb6xDVRzw895G4W7vvx60lFFur/1Rg==} + dependencies: + '@ethersproject/abstract-provider': 5.7.0 + '@ethersproject/abstract-signer': 5.7.0 + '@ethersproject/address': 5.7.0 + '@ethersproject/base64': 5.7.0 + '@ethersproject/basex': 5.7.0 + '@ethersproject/bignumber': 5.7.0 + '@ethersproject/bytes': 5.7.0 + '@ethersproject/constants': 5.7.0 + '@ethersproject/hash': 5.7.0 + '@ethersproject/logger': 5.7.0 + '@ethersproject/networks': 5.7.1 + '@ethersproject/properties': 5.7.0 + '@ethersproject/random': 5.7.0 + '@ethersproject/rlp': 5.7.0 + '@ethersproject/sha2': 5.7.0 + '@ethersproject/strings': 5.7.0 + '@ethersproject/transactions': 5.7.0 + '@ethersproject/web': 5.7.1 + bech32: 1.1.4 + ws: 7.4.6 + transitivePeerDependencies: + - bufferutil + - utf-8-validate + dev: false + + /@ethersproject/random@5.7.0: + resolution: {integrity: sha512-19WjScqRA8IIeWclFme75VMXSBvi4e6InrUNuaR4s5pTF2qNhcGdCUwdxUVGtDDqC00sDLCO93jPQoDUH4HVmQ==} + dependencies: + '@ethersproject/bytes': 5.7.0 + '@ethersproject/logger': 5.7.0 + dev: false + + /@ethersproject/rlp@5.7.0: + resolution: {integrity: sha512-rBxzX2vK8mVF7b0Tol44t5Tb8gomOHkj5guL+HhzQ1yBh/ydjGnpw6at+X6Iw0Kp3OzzzkcKp8N9r0W4kYSs9w==} + dependencies: + '@ethersproject/bytes': 5.7.0 + '@ethersproject/logger': 5.7.0 + dev: false + + /@ethersproject/sha2@5.7.0: + resolution: {integrity: sha512-gKlH42riwb3KYp0reLsFTokByAKoJdgFCwI+CCiX/k+Jm2mbNs6oOaCjYQSlI1+XBVejwH2KrmCbMAT/GnRDQw==} + dependencies: + '@ethersproject/bytes': 5.7.0 + '@ethersproject/logger': 5.7.0 + hash.js: 1.1.7 + dev: false + + /@ethersproject/signing-key@5.7.0: + resolution: {integrity: sha512-MZdy2nL3wO0u7gkB4nA/pEf8lu1TlFswPNmy8AiYkfKTdO6eXBJyUdmHO/ehm/htHw9K/qF8ujnTyUAD+Ry54Q==} + dependencies: + '@ethersproject/bytes': 5.7.0 + '@ethersproject/logger': 5.7.0 + '@ethersproject/properties': 5.7.0 + bn.js: 5.2.1 + elliptic: 6.5.4 + hash.js: 1.1.7 + dev: false + + /@ethersproject/strings@5.7.0: + resolution: {integrity: sha512-/9nu+lj0YswRNSH0NXYqrh8775XNyEdUQAuf3f+SmOrnVewcJ5SBNAjF7lpgehKi4abvNNXyf+HX86czCdJ8Mg==} + dependencies: + '@ethersproject/bytes': 5.7.0 + '@ethersproject/constants': 5.7.0 + '@ethersproject/logger': 5.7.0 + dev: false + + /@ethersproject/transactions@5.7.0: + resolution: {integrity: sha512-kmcNicCp1lp8qanMTC3RIikGgoJ80ztTyvtsFvCYpSCfkjhD0jZ2LOrnbcuxuToLIUYYf+4XwD1rP+B/erDIhQ==} + dependencies: + '@ethersproject/address': 5.7.0 + '@ethersproject/bignumber': 5.7.0 + '@ethersproject/bytes': 5.7.0 + '@ethersproject/constants': 5.7.0 + '@ethersproject/keccak256': 5.7.0 + '@ethersproject/logger': 5.7.0 + '@ethersproject/properties': 5.7.0 + '@ethersproject/rlp': 5.7.0 + '@ethersproject/signing-key': 5.7.0 + dev: false + + /@ethersproject/wallet@5.7.0: + resolution: {integrity: sha512-MhmXlJXEJFBFVKrDLB4ZdDzxcBxQ3rLyCkhNqVu3CDYvR97E+8r01UgrI+TI99Le+aYm/in/0vp86guJuM7FCA==} + dependencies: + '@ethersproject/abstract-provider': 5.7.0 + '@ethersproject/abstract-signer': 5.7.0 + '@ethersproject/address': 5.7.0 + '@ethersproject/bignumber': 5.7.0 + '@ethersproject/bytes': 5.7.0 + '@ethersproject/hash': 5.7.0 + '@ethersproject/hdnode': 5.7.0 + '@ethersproject/json-wallets': 5.7.0 + '@ethersproject/keccak256': 5.7.0 + '@ethersproject/logger': 5.7.0 + '@ethersproject/properties': 5.7.0 + '@ethersproject/random': 5.7.0 + '@ethersproject/signing-key': 5.7.0 + '@ethersproject/transactions': 5.7.0 + '@ethersproject/wordlists': 5.7.0 + dev: false + + /@ethersproject/web@5.7.1: + resolution: {integrity: sha512-Gueu8lSvyjBWL4cYsWsjh6MtMwM0+H4HvqFPZfB6dV8ctbP9zFAO73VG1cMWae0FLPCtz0peKPpZY8/ugJJX2w==} + dependencies: + '@ethersproject/base64': 5.7.0 + '@ethersproject/bytes': 5.7.0 + '@ethersproject/logger': 5.7.0 + '@ethersproject/properties': 5.7.0 + '@ethersproject/strings': 5.7.0 + dev: false + + /@ethersproject/wordlists@5.7.0: + resolution: {integrity: sha512-S2TFNJNfHWVHNE6cNDjbVlZ6MgE17MIxMbMg2zv3wn+3XSJGosL1m9ZVv3GXCf/2ymSsQ+hRI5IzoMJTG6aoVA==} + dependencies: + '@ethersproject/bytes': 5.7.0 + '@ethersproject/hash': 5.7.0 + '@ethersproject/logger': 5.7.0 + '@ethersproject/properties': 5.7.0 + '@ethersproject/strings': 5.7.0 + dev: false + + /@irys/arweave@0.0.2(debug@4.3.4): + resolution: {integrity: sha512-ddE5h4qXbl0xfGlxrtBIwzflaxZUDlDs43TuT0u1OMfyobHul4AA1VEX72Rpzw2bOh4vzoytSqA1jCM7x9YtHg==} + dependencies: + asn1.js: 5.4.1 + async-retry: 1.3.3 + axios: 1.6.8(debug@4.3.4) + base64-js: 1.5.1 + bignumber.js: 9.1.2 + transitivePeerDependencies: + - debug + dev: false + + /@irys/query@0.0.1(debug@4.3.4): + resolution: {integrity: sha512-7TCyR+Qn+F54IQQx5PlERgqNwgIQik8hY55iZl/silTHhCo1MI2pvx5BozqPUVCc8/KqRsc2nZd8Bc29XGUjRQ==} + engines: {node: '>=16.10.0'} + dependencies: + async-retry: 1.3.3 + axios: 1.6.8(debug@4.3.4) + transitivePeerDependencies: + - debug + dev: false + + /@irys/sdk@0.0.2(arweave@1.15.1)(debug@4.3.4): + resolution: {integrity: sha512-un/e/CmTpgT042gDwCN3AtISrR9OYGMY6V+442pFmSWKrwrsDoIXZ8VlLiYKnrtTm+yquGhjfYy0LDqGWq41pA==} + engines: {node: '>=16.10.0'} + hasBin: true + dependencies: + '@ethersproject/bignumber': 5.7.0 + '@ethersproject/contracts': 5.7.0 + '@ethersproject/providers': 5.7.2 + '@ethersproject/wallet': 5.7.0 + '@irys/query': 0.0.1(debug@4.3.4) + '@near-js/crypto': 0.0.3 + '@near-js/keystores-browser': 0.0.3 + '@near-js/providers': 0.0.4 + '@near-js/transactions': 0.1.1 + '@solana/web3.js': 1.91.8 + '@supercharge/promise-pool': 3.2.0 + algosdk: 1.24.1 + aptos: 1.8.5(debug@4.3.4) + arbundles: 0.10.1(arweave@1.15.1)(debug@4.3.4) + async-retry: 1.3.3 + axios: 1.6.8(debug@4.3.4) + base64url: 3.0.1 + bignumber.js: 9.1.2 + bs58: 5.0.0 + commander: 8.3.0 + csv: 5.5.3 + inquirer: 8.2.6 + js-sha256: 0.9.0 + mime-types: 2.1.35 + near-seed-phrase: 0.2.0 + transitivePeerDependencies: + - arweave + - bufferutil + - debug + - encoding + - utf-8-validate + dev: false + + /@metaplex-foundation/beet-solana@0.3.1: + resolution: {integrity: sha512-tgyEl6dvtLln8XX81JyBvWjIiEcjTkUwZbrM5dIobTmoqMuGewSyk9CClno8qsMsFdB5T3jC91Rjeqmu/6xk2g==} + dependencies: + '@metaplex-foundation/beet': 0.7.1 + '@solana/web3.js': 1.91.8 + bs58: 5.0.0 + debug: 4.3.4 + transitivePeerDependencies: + - bufferutil + - encoding + - supports-color + - utf-8-validate + dev: false + + /@metaplex-foundation/beet-solana@0.4.0: + resolution: {integrity: sha512-B1L94N3ZGMo53b0uOSoznbuM5GBNJ8LwSeznxBxJ+OThvfHQ4B5oMUqb+0zdLRfkKGS7Q6tpHK9P+QK0j3w2cQ==} + dependencies: + '@metaplex-foundation/beet': 0.7.1 + '@solana/web3.js': 1.91.8 + bs58: 5.0.0 + debug: 4.3.4 + transitivePeerDependencies: + - bufferutil + - encoding + - supports-color + - utf-8-validate + dev: false + + /@metaplex-foundation/beet-solana@0.4.1: + resolution: {integrity: sha512-/6o32FNUtwK8tjhotrvU/vorP7umBuRFvBZrC6XCk51aKidBHe5LPVPA5AjGPbV3oftMfRuXPNd9yAGeEqeCDQ==} + dependencies: + '@metaplex-foundation/beet': 0.7.1 + '@solana/web3.js': 1.91.8 + bs58: 5.0.0 + debug: 4.3.4 + transitivePeerDependencies: + - bufferutil + - encoding + - supports-color + - utf-8-validate + dev: false + + /@metaplex-foundation/beet@0.4.0: + resolution: {integrity: sha512-2OAKJnLatCc3mBXNL0QmWVQKAWK2C7XDfepgL0p/9+8oSx4bmRAFHFqptl1A/C0U5O3dxGwKfmKluW161OVGcA==} + dependencies: + ansicolors: 0.3.2 + bn.js: 5.2.1 + debug: 4.3.4 + transitivePeerDependencies: + - supports-color + dev: false + + /@metaplex-foundation/beet@0.6.1: + resolution: {integrity: sha512-OYgnijLFzw0cdUlRKH5POp0unQECPOW9muJ2X3QIVyak5G6I6l/rKo72sICgPLIFKdmsi2jmnkuLY7wp14iXdw==} + dependencies: + ansicolors: 0.3.2 + bn.js: 5.2.1 + debug: 4.3.4 + transitivePeerDependencies: + - supports-color + dev: false + + /@metaplex-foundation/beet@0.7.1: + resolution: {integrity: sha512-hNCEnS2WyCiYyko82rwuISsBY3KYpe828ubsd2ckeqZr7tl0WVLivGkoyA/qdiaaHEBGdGl71OpfWa2rqL3DiA==} + dependencies: + ansicolors: 0.3.2 + bn.js: 5.2.1 + debug: 4.3.4 + transitivePeerDependencies: + - supports-color + dev: false + + /@metaplex-foundation/cusper@0.0.2: + resolution: {integrity: sha512-S9RulC2fFCFOQraz61bij+5YCHhSO9llJegK8c8Y6731fSi6snUSQJdCUqYS8AIgR0TKbQvdvgSyIIdbDFZbBA==} + dev: false + + /@metaplex-foundation/js@0.20.1(arweave@1.15.1)(fastestsmallesttextencoderdecoder@1.0.22): + resolution: {integrity: sha512-aqiLoEiToXdfI5pS+17/GN/dIO2D31gLoVQvEKDQi9XcnOPVhfJerXDmwgKbhp79OGoYxtlvVw+b2suacoUzGQ==} + dependencies: + '@irys/sdk': 0.0.2(arweave@1.15.1)(debug@4.3.4) + '@metaplex-foundation/beet': 0.7.1 + '@metaplex-foundation/mpl-auction-house': 2.5.1(fastestsmallesttextencoderdecoder@1.0.22) + '@metaplex-foundation/mpl-bubblegum': 0.6.2(fastestsmallesttextencoderdecoder@1.0.22) + '@metaplex-foundation/mpl-candy-guard': 0.3.2 + '@metaplex-foundation/mpl-candy-machine': 5.1.0(fastestsmallesttextencoderdecoder@1.0.22) + '@metaplex-foundation/mpl-candy-machine-core': 0.1.2 + '@metaplex-foundation/mpl-token-metadata': 2.13.0(fastestsmallesttextencoderdecoder@1.0.22) + '@noble/ed25519': 1.7.3 + '@noble/hashes': 1.4.0 + '@solana/spl-account-compression': 0.1.10(@solana/web3.js@1.91.8) + '@solana/spl-token': 0.3.11(@solana/web3.js@1.91.8)(fastestsmallesttextencoderdecoder@1.0.22) + '@solana/web3.js': 1.91.8 + bignumber.js: 9.1.2 + bn.js: 5.2.1 + bs58: 5.0.0 + buffer: 6.0.3 + debug: 4.3.4 + eventemitter3: 4.0.7 + lodash.clonedeep: 4.5.0 + lodash.isequal: 4.5.0 + merkletreejs: 0.3.11 + mime: 3.0.0 + node-fetch: 2.7.0 + transitivePeerDependencies: + - arweave + - bufferutil + - encoding + - fastestsmallesttextencoderdecoder + - supports-color + - utf-8-validate + dev: false + + /@metaplex-foundation/mpl-auction-house@2.5.1(fastestsmallesttextencoderdecoder@1.0.22): + resolution: {integrity: sha512-O+IAdYVaoOvgACB8pm+1lF5BNEjl0COkqny2Ho8KQZwka6aC/vHbZ239yRwAMtJhf5992BPFdT4oifjyE0O+Mw==} + dependencies: + '@metaplex-foundation/beet': 0.6.1 + '@metaplex-foundation/beet-solana': 0.3.1 + '@metaplex-foundation/cusper': 0.0.2 + '@solana/spl-token': 0.3.11(@solana/web3.js@1.91.8)(fastestsmallesttextencoderdecoder@1.0.22) + '@solana/web3.js': 1.91.8 + bn.js: 5.2.1 + transitivePeerDependencies: + - bufferutil + - encoding + - fastestsmallesttextencoderdecoder + - supports-color + - utf-8-validate + dev: false + + /@metaplex-foundation/mpl-bubblegum@0.6.2(fastestsmallesttextencoderdecoder@1.0.22): + resolution: {integrity: sha512-4tF7/FFSNtpozuIGD7gMKcqK2D49eVXZ144xiowC5H1iBeu009/oj2m8Tj6n4DpYFKWJ2JQhhhk0a2q7x0Begw==} + dependencies: + '@metaplex-foundation/beet': 0.7.1 + '@metaplex-foundation/beet-solana': 0.4.0 + '@metaplex-foundation/cusper': 0.0.2 + '@metaplex-foundation/mpl-token-metadata': 2.13.0(fastestsmallesttextencoderdecoder@1.0.22) + '@solana/spl-account-compression': 0.1.10(@solana/web3.js@1.91.8) + '@solana/spl-token': 0.1.8 + '@solana/web3.js': 1.91.8 + bn.js: 5.2.1 + js-sha3: 0.8.0 + transitivePeerDependencies: + - bufferutil + - encoding + - fastestsmallesttextencoderdecoder + - supports-color + - utf-8-validate + dev: false + + /@metaplex-foundation/mpl-candy-guard@0.3.2: + resolution: {integrity: sha512-QWXzPDz+6OR3957LtfW6/rcGvFWS/0AeHJa/BUO2VEVQxN769dupsKGtrsS8o5RzXCeap3wrCtDSNxN3dnWu4Q==} + dependencies: + '@metaplex-foundation/beet': 0.4.0 + '@metaplex-foundation/beet-solana': 0.3.1 + '@metaplex-foundation/cusper': 0.0.2 + '@solana/web3.js': 1.91.8 + bn.js: 5.2.1 + transitivePeerDependencies: + - bufferutil + - encoding + - supports-color + - utf-8-validate + dev: false + + /@metaplex-foundation/mpl-candy-machine-core@0.1.2: + resolution: {integrity: sha512-jjDkRvMR+iykt7guQ7qVnOHTZedql0lq3xqWDMaenAUCH3Xrf2zKATThhJppIVNX1/YtgBOO3lGqhaFbaI4pCw==} + dependencies: + '@metaplex-foundation/beet': 0.4.0 + '@metaplex-foundation/beet-solana': 0.3.1 + '@metaplex-foundation/cusper': 0.0.2 + '@solana/web3.js': 1.91.8 + bn.js: 5.2.1 + transitivePeerDependencies: + - bufferutil + - encoding + - supports-color + - utf-8-validate + dev: false + + /@metaplex-foundation/mpl-candy-machine@5.1.0(fastestsmallesttextencoderdecoder@1.0.22): + resolution: {integrity: sha512-pjHpUpWVOCDxK3l6dXxfmJKNQmbjBqnm5ElOl1mJAygnzO8NIPQvrP89y6xSNyo8qZsJyt4ZMYUyD0TdbtKZXQ==} + dependencies: + '@metaplex-foundation/beet': 0.7.1 + '@metaplex-foundation/beet-solana': 0.4.1 + '@metaplex-foundation/cusper': 0.0.2 + '@solana/spl-token': 0.3.11(@solana/web3.js@1.91.8)(fastestsmallesttextencoderdecoder@1.0.22) + '@solana/web3.js': 1.91.8 + transitivePeerDependencies: + - bufferutil + - encoding + - fastestsmallesttextencoderdecoder + - supports-color + - utf-8-validate + dev: false + + /@metaplex-foundation/mpl-token-metadata@2.13.0(fastestsmallesttextencoderdecoder@1.0.22): + resolution: {integrity: sha512-Fl/8I0L9rv4bKTV/RAl5YIbJe9SnQPInKvLz+xR1fEc4/VQkuCn3RPgypfUMEKWmCznzaw4sApDxy6CFS4qmJw==} + dependencies: + '@metaplex-foundation/beet': 0.7.1 + '@metaplex-foundation/beet-solana': 0.4.1 + '@metaplex-foundation/cusper': 0.0.2 + '@solana/spl-token': 0.3.11(@solana/web3.js@1.91.8)(fastestsmallesttextencoderdecoder@1.0.22) + '@solana/web3.js': 1.91.8 + bn.js: 5.2.1 + debug: 4.3.4 + transitivePeerDependencies: + - bufferutil + - encoding + - fastestsmallesttextencoderdecoder + - supports-color + - utf-8-validate + dev: false + /@multiplechain/types@0.1.55: resolution: {integrity: sha512-9fYrLaDxX2pj9zfIbmvk1hPF3FH/bK+Q3uTF+k3zdsitP/HzQ1S9zImNz20Tvoqkk1ns+/8ecE0Y6GNowsDOQA==} dev: false @@ -21,204 +624,1660 @@ packages: /@multiplechain/utils@0.1.18: resolution: {integrity: sha512-UCoOOBJrawp/lInepxuoEiYwId0wMPg7rX8p78FLqzGl8f/b93sAtv7sP87/VVKwhdoEuNZ/uQjckycmNeks/w==} dependencies: - '@types/ws': 8.5.10 + '@types/ws': 8.5.10 + bignumber.js: 9.1.2 + web3-utils: 4.2.1 + ws: 8.16.0(bufferutil@4.0.8)(utf-8-validate@5.0.10) + transitivePeerDependencies: + - bufferutil + - utf-8-validate + dev: false + + /@near-js/crypto@0.0.3: + resolution: {integrity: sha512-3WC2A1a1cH8Cqrx+0iDjp1ASEEhxN/KHEMENYb0KZH6Hp5bXIY7Akt4quC7JlgJS5ESvEiLa40tS5h0zAhBWGw==} + dependencies: + '@near-js/types': 0.0.3 + bn.js: 5.2.1 + borsh: 0.7.0 + tweetnacl: 1.0.3 + dev: false + + /@near-js/crypto@0.0.4: + resolution: {integrity: sha512-2mSIVv6mZway1rQvmkktrXAFoUvy7POjrHNH3LekKZCMCs7qMM/23Hz2+APgxZPqoV2kjarSNOEYJjxO7zQ/rQ==} + dependencies: + '@near-js/types': 0.0.4 + bn.js: 5.2.1 + borsh: 0.7.0 + tweetnacl: 1.0.3 + dev: false + + /@near-js/keystores-browser@0.0.3: + resolution: {integrity: sha512-Ve/JQ1SBxdNk3B49lElJ8Y54AoBY+yOStLvdnUIpe2FBOczzwDCkcnPcMDV0NMwVlHpEnOWICWHbRbAkI5Vs+A==} + dependencies: + '@near-js/crypto': 0.0.3 + '@near-js/keystores': 0.0.3 + dev: false + + /@near-js/keystores@0.0.3: + resolution: {integrity: sha512-mnwLYUt4Td8u1I4QE1FBx2d9hMt3ofiriE93FfOluJ4XiqRqVFakFYiHg6pExg5iEkej/sXugBUFeQ4QizUnew==} + dependencies: + '@near-js/crypto': 0.0.3 + '@near-js/types': 0.0.3 + dev: false + + /@near-js/keystores@0.0.4: + resolution: {integrity: sha512-+vKafmDpQGrz5py1liot2hYSjPGXwihveeN+BL11aJlLqZnWBgYJUWCXG+uyGjGXZORuy2hzkKK6Hi+lbKOfVA==} + dependencies: + '@near-js/crypto': 0.0.4 + '@near-js/types': 0.0.4 + dev: false + + /@near-js/providers@0.0.4: + resolution: {integrity: sha512-g/2pJTYmsIlTW4mGqeRlqDN9pZeN+1E2/wfoMIf3p++boBVxVlaSebtQgawXAf2lkfhb9RqXz5pHqewXIkTBSw==} + dependencies: + '@near-js/transactions': 0.1.0 + '@near-js/types': 0.0.3 + '@near-js/utils': 0.0.3 + bn.js: 5.2.1 + borsh: 0.7.0 + http-errors: 1.8.1 + optionalDependencies: + node-fetch: 2.7.0 + transitivePeerDependencies: + - encoding + dev: false + + /@near-js/signers@0.0.3: + resolution: {integrity: sha512-u1R+DDIua5PY1PDFnpVYqdMgQ7c4dyeZsfqMjE7CtgzdqupgTYCXzJjBubqMlAyAx843PoXmLt6CSSKcMm0WUA==} + dependencies: + '@near-js/crypto': 0.0.3 + '@near-js/keystores': 0.0.3 + js-sha256: 0.9.0 + dev: false + + /@near-js/signers@0.0.4: + resolution: {integrity: sha512-xCglo3U/WIGsz/izPGFMegS5Q3PxOHYB8a1E7RtVhNm5QdqTlQldLCm/BuMg2G/u1l1ZZ0wdvkqRTG9joauf3Q==} + dependencies: + '@near-js/crypto': 0.0.4 + '@near-js/keystores': 0.0.4 + js-sha256: 0.9.0 + dev: false + + /@near-js/transactions@0.1.0: + resolution: {integrity: sha512-OrrDFqhX0rtH+6MV3U3iS+zmzcPQI+L4GJi9na4Uf8FgpaVPF0mtSmVrpUrS5CC3LwWCzcYF833xGYbXOV4Kfg==} + dependencies: + '@near-js/crypto': 0.0.3 + '@near-js/signers': 0.0.3 + '@near-js/types': 0.0.3 + '@near-js/utils': 0.0.3 + bn.js: 5.2.1 + borsh: 0.7.0 + js-sha256: 0.9.0 + dev: false + + /@near-js/transactions@0.1.1: + resolution: {integrity: sha512-Fk83oLLFK7nz4thawpdv9bGyMVQ2i48iUtZEVYhuuuqevl17tSXMlhle9Me1ZbNyguJG/cWPdNybe1UMKpyGxA==} + dependencies: + '@near-js/crypto': 0.0.4 + '@near-js/signers': 0.0.4 + '@near-js/types': 0.0.4 + '@near-js/utils': 0.0.4 + bn.js: 5.2.1 + borsh: 0.7.0 + js-sha256: 0.9.0 + dev: false + + /@near-js/types@0.0.3: + resolution: {integrity: sha512-gC3iGUT+r2JjVsE31YharT+voat79ToMUMLCGozHjp/R/UW1M2z4hdpqTUoeWUBGBJuVc810gNTneHGx0jvzwQ==} + dependencies: + bn.js: 5.2.1 + dev: false + + /@near-js/types@0.0.4: + resolution: {integrity: sha512-8TTMbLMnmyG06R5YKWuS/qFG1tOA3/9lX4NgBqQPsvaWmDsa+D+QwOkrEHDegped0ZHQwcjAXjKML1S1TyGYKg==} + dependencies: + bn.js: 5.2.1 + dev: false + + /@near-js/utils@0.0.3: + resolution: {integrity: sha512-J72n/EL0VfLRRb4xNUF4rmVrdzMkcmkwJOhBZSTWz3PAZ8LqNeU9ZConPfMvEr6lwdaD33ZuVv70DN6IIjPr1A==} + dependencies: + '@near-js/types': 0.0.3 + bn.js: 5.2.1 + depd: 2.0.0 + mustache: 4.2.0 + dev: false + + /@near-js/utils@0.0.4: + resolution: {integrity: sha512-mPUEPJbTCMicGitjEGvQqOe8AS7O4KkRCxqd0xuE/X6gXF1jz1pYMZn4lNUeUz2C84YnVSGLAM0o9zcN6Y4hiA==} + dependencies: + '@near-js/types': 0.0.4 + bn.js: 5.2.1 + depd: 2.0.0 + mustache: 4.2.0 + dev: false + + /@noble/curves@1.3.0: + resolution: {integrity: sha512-t01iSXPuN+Eqzb4eBX0S5oubSqXbK/xXa1Ne18Hj8f9pStxztHCE2gfboSp/dZRLSqfuLpRK2nDXDK+W9puocA==} + dependencies: + '@noble/hashes': 1.3.3 + dev: false + + /@noble/curves@1.4.0: + resolution: {integrity: sha512-p+4cb332SFCrReJkCYe8Xzm0OWi4Jji5jVdIZRL/PmacmDkFNw6MrrV+gGpiPxLHbV+zKFRywUWbaseT+tZRXg==} + dependencies: + '@noble/hashes': 1.4.0 + dev: false + + /@noble/ed25519@1.7.3: + resolution: {integrity: sha512-iR8GBkDt0Q3GyaVcIu7mSsVIqnFbkbRzGLWlvhwunacoLwt4J3swfKhfaM6rN6WY+TBGoYT1GtT1mIh2/jGbRQ==} + dev: false + + /@noble/hashes@1.1.3: + resolution: {integrity: sha512-CE0FCR57H2acVI5UOzIGSSIYxZ6v/HOhDR0Ro9VLyhnzLwx0o8W1mmgaqlEUx4049qJDlIBRztv5k+MM8vbO3A==} + dev: false + + /@noble/hashes@1.3.3: + resolution: {integrity: sha512-V7/fPHgl+jsVPXqqeOzT8egNj2iBIVt+ECeMMG8TdcnTikP3oaBtUVqpT/gYCR68aEBJSF+XbYUxStjbFMqIIA==} + engines: {node: '>= 16'} + dev: false + + /@noble/hashes@1.4.0: + resolution: {integrity: sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg==} + engines: {node: '>= 16'} + dev: false + + /@randlabs/communication-bridge@1.0.1: + resolution: {integrity: sha512-CzS0U8IFfXNK7QaJFE4pjbxDGfPjbXBEsEaCn9FN15F+ouSAEUQkva3Gl66hrkBZOGexKFEWMwUHIDKpZ2hfVg==} + requiresBuild: true + dev: false + optional: true + + /@randlabs/myalgo-connect@1.4.2: + resolution: {integrity: sha512-K9hEyUi7G8tqOp7kWIALJLVbGCByhilcy6123WfcorxWwiE1sbQupPyIU5f3YdQK6wMjBsyTWiLW52ZBMp7sXA==} + requiresBuild: true + dependencies: + '@randlabs/communication-bridge': 1.0.1 + dev: false + optional: true + + /@scure/base@1.1.6: + resolution: {integrity: sha512-ok9AWwhcgYuGG3Zfhyqg+zwl+Wn5uE+dwC0NV/2qQkx4dABbb/bx96vWu8NSj+BNjjSjno+JRYRjle1jV08k3g==} + dev: false + + /@scure/bip32@1.3.3: + resolution: {integrity: sha512-LJaN3HwRbfQK0X1xFSi0Q9amqOgzQnnDngIt+ZlsBC3Bm7/nE7K0kwshZHyaru79yIVRv/e1mQAjZyuZG6jOFQ==} + dependencies: + '@noble/curves': 1.3.0 + '@noble/hashes': 1.3.3 + '@scure/base': 1.1.6 + dev: false + + /@scure/bip39@1.1.0: + resolution: {integrity: sha512-pwrPOS16VeTKg98dYXQyIjJEcWfz7/1YJIwxUEPFfQPtc86Ym/1sVgQ2RLoD43AazMk2l/unK4ITySSpW2+82w==} + dependencies: + '@noble/hashes': 1.1.3 + '@scure/base': 1.1.6 + dev: false + + /@scure/bip39@1.2.2: + resolution: {integrity: sha512-HYf9TUXG80beW+hGAt3TRM8wU6pQoYur9iNypTROm42dorCGmLnFe3eWjz3gOq6G62H2WRh0FCzAR1PI+29zIA==} + dependencies: + '@noble/hashes': 1.3.3 + '@scure/base': 1.1.6 + dev: false + + /@solana/buffer-layout-utils@0.2.0: + resolution: {integrity: sha512-szG4sxgJGktbuZYDg2FfNmkMi0DYQoVjN2h7ta1W1hPrwzarcFLBq9UpX1UjNXsNpT9dn+chgprtWGioUAr4/g==} + engines: {node: '>= 10'} + dependencies: + '@solana/buffer-layout': 4.0.1 + '@solana/web3.js': 1.91.8 + bigint-buffer: 1.1.5 + bignumber.js: 9.1.2 + transitivePeerDependencies: + - bufferutil + - encoding + - utf-8-validate + dev: false + + /@solana/buffer-layout@4.0.1: + resolution: {integrity: sha512-E1ImOIAD1tBZFRdjeM4/pzTiTApC0AOBGwyAMS4fwIodCWArzJ3DWdoh8cKxeFM2fElkxBh2Aqts1BPC373rHA==} + engines: {node: '>=5.10'} + dependencies: + buffer: 6.0.3 + dev: false + + /@solana/codecs-core@2.0.0-preview.2: + resolution: {integrity: sha512-gLhCJXieSCrAU7acUJjbXl+IbGnqovvxQLlimztPoGgfLQ1wFYu+XJswrEVQqknZYK1pgxpxH3rZ+OKFs0ndQg==} + dependencies: + '@solana/errors': 2.0.0-preview.2 + dev: false + + /@solana/codecs-data-structures@2.0.0-preview.2: + resolution: {integrity: sha512-Xf5vIfromOZo94Q8HbR04TbgTwzigqrKII0GjYr21K7rb3nba4hUW2ir8kguY7HWFBcjHGlU5x3MevKBOLp3Zg==} + dependencies: + '@solana/codecs-core': 2.0.0-preview.2 + '@solana/codecs-numbers': 2.0.0-preview.2 + '@solana/errors': 2.0.0-preview.2 + dev: false + + /@solana/codecs-numbers@2.0.0-preview.2: + resolution: {integrity: sha512-aLZnDTf43z4qOnpTcDsUVy1Ci9im1Md8thWipSWbE+WM9ojZAx528oAql+Cv8M8N+6ALKwgVRhPZkto6E59ARw==} + dependencies: + '@solana/codecs-core': 2.0.0-preview.2 + '@solana/errors': 2.0.0-preview.2 + dev: false + + /@solana/codecs-strings@2.0.0-preview.2(fastestsmallesttextencoderdecoder@1.0.22): + resolution: {integrity: sha512-EgBwY+lIaHHgMJIqVOGHfIfpdmmUDNoNO/GAUGeFPf+q0dF+DtwhJPEMShhzh64X2MeCZcmSO6Kinx0Bvmmz2g==} + peerDependencies: + fastestsmallesttextencoderdecoder: ^1.0.22 + dependencies: + '@solana/codecs-core': 2.0.0-preview.2 + '@solana/codecs-numbers': 2.0.0-preview.2 + '@solana/errors': 2.0.0-preview.2 + fastestsmallesttextencoderdecoder: 1.0.22 + dev: false + + /@solana/codecs@2.0.0-preview.2(fastestsmallesttextencoderdecoder@1.0.22): + resolution: {integrity: sha512-4HHzCD5+pOSmSB71X6w9ptweV48Zj1Vqhe732+pcAQ2cMNnN0gMPMdDq7j3YwaZDZ7yrILVV/3+HTnfT77t2yA==} + dependencies: + '@solana/codecs-core': 2.0.0-preview.2 + '@solana/codecs-data-structures': 2.0.0-preview.2 + '@solana/codecs-numbers': 2.0.0-preview.2 + '@solana/codecs-strings': 2.0.0-preview.2(fastestsmallesttextencoderdecoder@1.0.22) + '@solana/options': 2.0.0-preview.2 + transitivePeerDependencies: + - fastestsmallesttextencoderdecoder + dev: false + + /@solana/errors@2.0.0-preview.2: + resolution: {integrity: sha512-H2DZ1l3iYF5Rp5pPbJpmmtCauWeQXRJapkDg8epQ8BJ7cA2Ut/QEtC3CMmw/iMTcuS6uemFNLcWvlOfoQhvQuA==} + hasBin: true + dependencies: + chalk: 5.3.0 + commander: 12.0.0 + dev: false + + /@solana/options@2.0.0-preview.2: + resolution: {integrity: sha512-FAHqEeH0cVsUOTzjl5OfUBw2cyT8d5Oekx4xcn5hn+NyPAfQJgM3CEThzgRD6Q/4mM5pVUnND3oK/Mt1RzSE/w==} + dependencies: + '@solana/codecs-core': 2.0.0-preview.2 + '@solana/codecs-numbers': 2.0.0-preview.2 + dev: false + + /@solana/spl-account-compression@0.1.10(@solana/web3.js@1.91.8): + resolution: {integrity: sha512-IQAOJrVOUo6LCgeWW9lHuXo6JDbi4g3/RkQtvY0SyalvSWk9BIkHHe4IkAzaQw8q/BxEVBIjz8e9bNYWIAESNw==} + engines: {node: '>=16'} + peerDependencies: + '@solana/web3.js': ^1.50.1 + dependencies: + '@metaplex-foundation/beet': 0.7.1 + '@metaplex-foundation/beet-solana': 0.4.1 + '@solana/web3.js': 1.91.8 + bn.js: 5.2.1 + borsh: 0.7.0 + js-sha3: 0.8.0 + typescript-collections: 1.3.3 + transitivePeerDependencies: + - bufferutil + - encoding + - supports-color + - utf-8-validate + dev: false + + /@solana/spl-token-group@0.0.4(@solana/web3.js@1.91.8)(fastestsmallesttextencoderdecoder@1.0.22): + resolution: {integrity: sha512-7+80nrEMdUKlK37V6kOe024+T7J4nNss0F8LQ9OOPYdWCCfJmsGUzVx2W3oeizZR4IHM6N4yC9v1Xqwc3BTPWw==} + engines: {node: '>=16'} + peerDependencies: + '@solana/web3.js': ^1.91.6 + dependencies: + '@solana/codecs': 2.0.0-preview.2(fastestsmallesttextencoderdecoder@1.0.22) + '@solana/spl-type-length-value': 0.1.0 + '@solana/web3.js': 1.91.8 + transitivePeerDependencies: + - fastestsmallesttextencoderdecoder + dev: false + + /@solana/spl-token-metadata@0.1.4(@solana/web3.js@1.91.8)(fastestsmallesttextencoderdecoder@1.0.22): + resolution: {integrity: sha512-N3gZ8DlW6NWDV28+vCCDJoTqaCZiF/jDUnk3o8GRkAFzHObiR60Bs1gXHBa8zCPdvOwiG6Z3dg5pg7+RW6XNsQ==} + engines: {node: '>=16'} + peerDependencies: + '@solana/web3.js': ^1.91.6 + dependencies: + '@solana/codecs': 2.0.0-preview.2(fastestsmallesttextencoderdecoder@1.0.22) + '@solana/spl-type-length-value': 0.1.0 + '@solana/web3.js': 1.91.8 + transitivePeerDependencies: + - fastestsmallesttextencoderdecoder + dev: false + + /@solana/spl-token@0.1.8: + resolution: {integrity: sha512-LZmYCKcPQDtJgecvWOgT/cnoIQPWjdH+QVyzPcFvyDUiT0DiRjZaam4aqNUyvchLFhzgunv3d9xOoyE34ofdoQ==} + engines: {node: '>= 10'} + dependencies: + '@babel/runtime': 7.24.5 + '@solana/web3.js': 1.91.8 + bn.js: 5.2.1 + buffer: 6.0.3 + buffer-layout: 1.2.2 + dotenv: 10.0.0 + transitivePeerDependencies: + - bufferutil + - encoding + - utf-8-validate + dev: false + + /@solana/spl-token@0.3.11(@solana/web3.js@1.91.8)(fastestsmallesttextencoderdecoder@1.0.22): + resolution: {integrity: sha512-bvohO3rIMSVL24Pb+I4EYTJ6cL82eFpInEXD/I8K8upOGjpqHsKUoAempR/RnUlI1qSFNyFlWJfu6MNUgfbCQQ==} + engines: {node: '>=16'} + peerDependencies: + '@solana/web3.js': ^1.88.0 + dependencies: + '@solana/buffer-layout': 4.0.1 + '@solana/buffer-layout-utils': 0.2.0 + '@solana/spl-token-metadata': 0.1.4(@solana/web3.js@1.91.8)(fastestsmallesttextencoderdecoder@1.0.22) + '@solana/web3.js': 1.91.8 + buffer: 6.0.3 + transitivePeerDependencies: + - bufferutil + - encoding + - fastestsmallesttextencoderdecoder + - utf-8-validate + dev: false + + /@solana/spl-token@0.4.6(@solana/web3.js@1.91.8)(fastestsmallesttextencoderdecoder@1.0.22): + resolution: {integrity: sha512-1nCnUqfHVtdguFciVWaY/RKcQz1IF4b31jnKgAmjU9QVN1q7dRUkTEWJZgTYIEtsULjVnC9jRqlhgGN39WbKKA==} + engines: {node: '>=16'} + peerDependencies: + '@solana/web3.js': ^1.91.6 + dependencies: + '@solana/buffer-layout': 4.0.1 + '@solana/buffer-layout-utils': 0.2.0 + '@solana/spl-token-group': 0.0.4(@solana/web3.js@1.91.8)(fastestsmallesttextencoderdecoder@1.0.22) + '@solana/spl-token-metadata': 0.1.4(@solana/web3.js@1.91.8)(fastestsmallesttextencoderdecoder@1.0.22) + '@solana/web3.js': 1.91.8 + buffer: 6.0.3 + transitivePeerDependencies: + - bufferutil + - encoding + - fastestsmallesttextencoderdecoder + - utf-8-validate + dev: false + + /@solana/spl-type-length-value@0.1.0: + resolution: {integrity: sha512-JBMGB0oR4lPttOZ5XiUGyvylwLQjt1CPJa6qQ5oM+MBCndfjz2TKKkw0eATlLLcYmq1jBVsNlJ2cD6ns2GR7lA==} + engines: {node: '>=16'} + dependencies: + buffer: 6.0.3 + dev: false + + /@solana/web3.js@1.91.8: + resolution: {integrity: sha512-USa6OS1jbh8zOapRJ/CBZImZ8Xb7AJjROZl5adql9TpOoBN9BUzyyouS5oPuZHft7S7eB8uJPuXWYjMi6BHgOw==} + dependencies: + '@babel/runtime': 7.24.5 + '@noble/curves': 1.4.0 + '@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.0 + node-fetch: 2.7.0 + rpc-websockets: 7.11.0 + superstruct: 0.14.2 + transitivePeerDependencies: + - bufferutil + - encoding + - utf-8-validate + dev: false + + /@supercharge/promise-pool@3.2.0: + resolution: {integrity: sha512-pj0cAALblTZBPtMltWOlZTQSLT07jIaFNeM8TWoJD1cQMgDB9mcMlVMoetiB35OzNJpqQ2b+QEtwiR9f20mADg==} + engines: {node: '>=8'} + dev: false + + /@types/connect@3.4.38: + resolution: {integrity: sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==} + dependencies: + '@types/node': 20.12.7 + dev: false + + /@types/node@11.11.6: + resolution: {integrity: sha512-Exw4yUWMBXM3X+8oqzJNRqZSwUAaS4+7NdvHqQuFi/d+synz++xmX3QIf+BFqneW8N31R8Ky+sikfZUXq07ggQ==} + dev: false + + /@types/node@12.20.55: + resolution: {integrity: sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ==} + dev: false + + /@types/node@20.12.7: + resolution: {integrity: sha512-wq0cICSkRLVaf3UGLMGItu/PtdY7oaXaI/RVU+xliKVOtRna3PRY57ZDfztpDL0n11vfymMUnXv8QwYCO7L1wg==} + dependencies: + undici-types: 5.26.5 + dev: false + + /@types/ws@7.4.7: + resolution: {integrity: sha512-JQbbmxZTZehdc2iszGKs5oC3NFnjeay7mtAWrdt7qNtAVK0g19muApzAy4bm9byz79xa2ZnO/BOBC2R8RC5Lww==} + dependencies: + '@types/node': 20.12.7 + dev: false + + /@types/ws@8.5.10: + resolution: {integrity: sha512-vmQSUcfalpIq0R9q7uTo2lXs6eGIpt9wtnLdMv9LVpIjCA/+ufZRozlVoVelIYixx1ugCBKDhn89vnsEGOCx9A==} + dependencies: + '@types/node': 20.12.7 + dev: false + + /JSONStream@1.3.5: + resolution: {integrity: sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==} + hasBin: true + dependencies: + jsonparse: 1.3.1 + through: 2.3.8 + dev: false + + /aes-js@3.0.0: + resolution: {integrity: sha512-H7wUZRn8WpTq9jocdxQ2c8x2sKo9ZVmzfRE13GiNJXfp7NcKYEdvl3vspKjXox6RIG2VtaRe4JFvxG4rqp2Zuw==} + dev: false + + /agentkeepalive@4.5.0: + resolution: {integrity: sha512-5GG/5IbQQpC9FpkRGsSvZI5QYeSCzlJHdpBQntCsuTOxhKD8lqKhrleg2Yi7yvMIf82Ycmmqln9U8V9qwEiJew==} + engines: {node: '>= 8.0.0'} + dependencies: + humanize-ms: 1.2.1 + dev: false + + /algo-msgpack-with-bigint@2.1.1: + resolution: {integrity: sha512-F1tGh056XczEaEAqu7s+hlZUDWwOBT70Eq0lfMpBP2YguSQVyxRbprLq5rELXKQOyOaixTWYhMeMQMzP0U5FoQ==} + engines: {node: '>= 10'} + dev: false + + /algosdk@1.24.1: + resolution: {integrity: sha512-9moZxdqeJ6GdE4N6fA/GlUP4LrbLZMYcYkt141J4Ss68OfEgH9qW0wBuZ3ZOKEx/xjc5bg7mLP2Gjg7nwrkmww==} + engines: {node: '>=14.0.0'} + dependencies: + algo-msgpack-with-bigint: 2.1.1 + buffer: 6.0.3 + cross-fetch: 3.1.8 + hi-base32: 0.5.1 + js-sha256: 0.9.0 + js-sha3: 0.8.0 + js-sha512: 0.8.0 + json-bigint: 1.0.0 + tweetnacl: 1.0.3 + vlq: 2.0.4 + transitivePeerDependencies: + - encoding + dev: false + + /ansi-escapes@4.3.2: + resolution: {integrity: sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==} + engines: {node: '>=8'} + dependencies: + type-fest: 0.21.3 + dev: false + + /ansi-regex@5.0.1: + resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} + engines: {node: '>=8'} + dev: false + + /ansi-styles@4.3.0: + resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} + engines: {node: '>=8'} + dependencies: + color-convert: 2.0.1 + dev: false + + /ansicolors@0.3.2: + resolution: {integrity: sha512-QXu7BPrP29VllRxH8GwB7x5iX5qWKAAMLqKQGWTeLWVlNHNOpVMJ91dsxQAIWXpjuW5wqvxu3Jd/nRjrJ+0pqg==} + dev: false + + /aptos@1.8.5(debug@4.3.4): + resolution: {integrity: sha512-iQxliWesNHjGQ5YYXCyss9eg4+bDGQWqAZa73vprqGQ9tungK0cRjUI2fmnp63Ed6UG6rurHrL+b0ckbZAOZZQ==} + engines: {node: '>=11.0.0'} + dependencies: + '@noble/hashes': 1.1.3 + '@scure/bip39': 1.1.0 + axios: 0.27.2(debug@4.3.4) + form-data: 4.0.0 + tweetnacl: 1.0.3 + transitivePeerDependencies: + - debug + dev: false + + /arbundles@0.10.1(arweave@1.15.1)(debug@4.3.4): + resolution: {integrity: sha512-QYFepxessLCirvRkQK9iQmjxjHz+s50lMNGRwZwpyPWLohuf6ISyj1gkFXJHlMT+rNSrsHxb532glHnKbjwu3A==} + dependencies: + '@ethersproject/bytes': 5.7.0 + '@ethersproject/hash': 5.7.0 + '@ethersproject/providers': 5.7.2 + '@ethersproject/signing-key': 5.7.0 + '@ethersproject/transactions': 5.7.0 + '@ethersproject/wallet': 5.7.0 + '@irys/arweave': 0.0.2(debug@4.3.4) + '@noble/ed25519': 1.7.3 + base64url: 3.0.1 + bs58: 4.0.1 + keccak: 3.0.4 + secp256k1: 5.0.0 + optionalDependencies: + '@randlabs/myalgo-connect': 1.4.2 + algosdk: 1.24.1 + arweave-stream-tx: 1.2.2(arweave@1.15.1) + multistream: 4.1.0 + tmp-promise: 3.0.3 + transitivePeerDependencies: + - arweave + - bufferutil + - debug + - encoding + - utf-8-validate + dev: false + + /arconnect@0.4.2: + resolution: {integrity: sha512-Jkpd4QL3TVqnd3U683gzXmZUVqBUy17DdJDuL/3D9rkysLgX6ymJ2e+sR+xyZF5Rh42CBqDXWNMmCjBXeP7Gbw==} + dependencies: + arweave: 1.15.1 + dev: false + optional: true + + /arweave-stream-tx@1.2.2(arweave@1.15.1): + resolution: {integrity: sha512-bNt9rj0hbAEzoUZEF2s6WJbIz8nasZlZpxIw03Xm8fzb9gRiiZlZGW3lxQLjfc9Z0VRUWDzwtqoYeEoB/JDToQ==} + requiresBuild: true + peerDependencies: + arweave: ^1.10.0 + dependencies: + arweave: 1.15.1 + exponential-backoff: 3.1.1 + dev: false + optional: true + + /arweave@1.15.1: + resolution: {integrity: sha512-rT7FOwqdudd5npqp4xOYdDT2035LtpcqePjwirh4wjRiEtVsz1FZkRiM2Yj+fOAwYzOm/hNG0GDOipDSaiEGGQ==} + engines: {node: '>=18'} + dependencies: + arconnect: 0.4.2 + asn1.js: 5.4.1 + base64-js: 1.5.1 + bignumber.js: 9.1.2 + dev: false + optional: true + + /asn1.js@5.4.1: + resolution: {integrity: sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA==} + dependencies: + bn.js: 4.12.0 + inherits: 2.0.4 + minimalistic-assert: 1.0.1 + safer-buffer: 2.1.2 + dev: false + + /async-retry@1.3.3: + resolution: {integrity: sha512-wfr/jstw9xNi/0teMHrRW7dsz3Lt5ARhYNZ2ewpadnhaIp5mbALhOAP+EAdsC7t4Z6wqsDVv9+W6gm1Dk9mEyw==} + dependencies: + retry: 0.13.1 + dev: false + + /asynckit@0.4.0: + resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} + dev: false + + /available-typed-arrays@1.0.7: + resolution: {integrity: sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==} + engines: {node: '>= 0.4'} + dependencies: + possible-typed-array-names: 1.0.0 + dev: false + + /axios@0.27.2(debug@4.3.4): + resolution: {integrity: sha512-t+yRIyySRTp/wua5xEr+z1q60QmLq8ABsS5O9Me1AsE5dfKqgnCFzwiCZZ/cGNd1lq4/7akDWMxdhVlucjmnOQ==} + dependencies: + follow-redirects: 1.15.6(debug@4.3.4) + form-data: 4.0.0 + transitivePeerDependencies: + - debug + dev: false + + /axios@1.6.8(debug@4.3.4): + resolution: {integrity: sha512-v/ZHtJDU39mDpyBoFVkETcd/uNdxrWRrg3bKpOKzXFA6Bvqopts6ALSMU3y6ijYxbw2B+wPrIv46egTzJXCLGQ==} + dependencies: + follow-redirects: 1.15.6(debug@4.3.4) + form-data: 4.0.0 + proxy-from-env: 1.1.0 + transitivePeerDependencies: + - debug + dev: false + + /base-x@3.0.9: + resolution: {integrity: sha512-H7JU6iBHTal1gp56aKoaa//YUxEaAOUiydvrV/pILqIHXTtqxSkATOnDA2u+jZ/61sD+L/412+7kzXRtWukhpQ==} + dependencies: + safe-buffer: 5.2.1 + dev: false + + /base-x@4.0.0: + resolution: {integrity: sha512-FuwxlW4H5kh37X/oW59pwTzzTKRzfrrQwhmyspRM7swOEZcHtDZSCt45U6oKgtuFE+WYPblePMVIPR4RZrh/hw==} + dev: false + + /base64-js@1.5.1: + resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} + dev: false + + /base64url@3.0.1: + resolution: {integrity: sha512-ir1UPr3dkwexU7FdV8qBBbNDRUhMmIekYMFZfi+C/sLNnRESKPl23nB9b2pltqfOQNnGzsDdId90AEtG5tCx4A==} + engines: {node: '>=6.0.0'} + dev: false + + /bech32@1.1.4: + resolution: {integrity: sha512-s0IrSOzLlbvX7yp4WBfPITzpAU8sqQcpsmwXDiKwrG4r491vwCO/XpejasRNl0piBMe/DvP4Tz0mIS/X1DPJBQ==} + dev: false + + /bigint-buffer@1.1.5: + resolution: {integrity: sha512-trfYco6AoZ+rKhKnxA0hgX0HAbVP/s808/EuDSe2JDzUnCp/xAsli35Orvk67UrTEcwuxZqYZDmfA2RXJgxVvA==} + engines: {node: '>= 10.0.0'} + requiresBuild: true + dependencies: + bindings: 1.5.0 + dev: false + + /bignumber.js@9.1.2: + resolution: {integrity: sha512-2/mKyZH9K85bzOEfhXDBFZTGd1CTs+5IHpeFQo9luiBG7hghdC851Pj2WAhb6E3R6b9tZj/XKhbg4fum+Kepug==} + dev: false + + /bindings@1.5.0: + resolution: {integrity: sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==} + dependencies: + file-uri-to-path: 1.0.0 + dev: false + + /bip39-light@1.0.7: + resolution: {integrity: sha512-WDTmLRQUsiioBdTs9BmSEmkJza+8xfJmptsNJjxnoq3EydSa/ZBXT6rm66KoT3PJIRYMnhSKNR7S9YL1l7R40Q==} + dependencies: + create-hash: 1.2.0 + pbkdf2: 3.1.2 + dev: false + + /bip39@3.0.2: + resolution: {integrity: sha512-J4E1r2N0tUylTKt07ibXvhpT2c5pyAFgvuA5q1H9uDy6dEGpjV8jmymh3MTYJDLCNbIVClSB9FbND49I6N24MQ==} + dependencies: + '@types/node': 11.11.6 + create-hash: 1.2.0 + pbkdf2: 3.1.2 + randombytes: 2.1.0 + dev: false + + /bl@4.1.0: + resolution: {integrity: sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==} + dependencies: + buffer: 5.7.1 + inherits: 2.0.4 + readable-stream: 3.6.2 + dev: false + + /bn.js@4.11.6: + resolution: {integrity: sha512-XWwnNNFCuuSQ0m3r3C4LE3EiORltHd9M05pq6FOlVeiophzRbMo50Sbz1ehl8K3Z+jw9+vmgnXefY1hz8X+2wA==} + dev: false + + /bn.js@4.12.0: + resolution: {integrity: sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==} + dev: false + + /bn.js@5.2.1: + resolution: {integrity: sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ==} + dev: false + + /borsh@0.7.0: + resolution: {integrity: sha512-CLCsZGIBCFnPtkNnieW/a8wmreDmfUtjU2m9yHrzPXIlNbqVs0AQrSatSG6vdNYUqdc83tkQi2eHfF98ubzQLA==} + dependencies: + bn.js: 5.2.1 + bs58: 4.0.1 + text-encoding-utf-8: 1.0.2 + dev: false + + /brorand@1.1.0: + resolution: {integrity: sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w==} + dev: false + + /bs58@4.0.1: + resolution: {integrity: sha512-Ok3Wdf5vOIlBrgCvTq96gBkJw+JUEzdBgyaza5HLtPm7yTHkjRy8+JzNyHF7BHa0bNWOQIp3m5YF0nnFcOIKLw==} + dependencies: + base-x: 3.0.9 + dev: false + + /bs58@5.0.0: + resolution: {integrity: sha512-r+ihvQJvahgYT50JD05dyJNKlmmSlMoOGwn1lCcEzanPglg7TxYjioQUYehQ9mAR/+hOSd2jRc/Z2y5UxBymvQ==} + dependencies: + base-x: 4.0.0 + dev: false + + /buffer-layout@1.2.2: + resolution: {integrity: sha512-kWSuLN694+KTk8SrYvCqwP2WcgQjoRCiF5b4QDvkkz8EmgD+aWAIceGFKMIAdmF/pH+vpgNV3d3kAKorcdAmWA==} + engines: {node: '>=4.5'} + dev: false + + /buffer-reverse@1.0.1: + resolution: {integrity: sha512-M87YIUBsZ6N924W57vDwT/aOu8hw7ZgdByz6ijksLjmHJELBASmYTTlNHRgjE+pTsT9oJXGaDSgqqwfdHotDUg==} + dev: false + + /buffer@5.7.1: + resolution: {integrity: sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==} + dependencies: + base64-js: 1.5.1 + ieee754: 1.2.1 + dev: false + + /buffer@6.0.3: + resolution: {integrity: sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==} + dependencies: + base64-js: 1.5.1 + ieee754: 1.2.1 + dev: false + + /bufferutil@4.0.8: + resolution: {integrity: sha512-4T53u4PdgsXqKaIctwF8ifXlRTTmEPJ8iEPWFdGZvcf7sbwYo6FKFEX9eNNAnzFZ7EzJAQ3CJeOtCRA4rDp7Pw==} + engines: {node: '>=6.14.2'} + requiresBuild: true + dependencies: + node-gyp-build: 4.8.1 + dev: false + + /call-bind@1.0.7: + resolution: {integrity: sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==} + engines: {node: '>= 0.4'} + dependencies: + es-define-property: 1.0.0 + es-errors: 1.3.0 + function-bind: 1.1.2 + get-intrinsic: 1.2.4 + set-function-length: 1.2.2 + dev: false + + /chalk@4.1.2: + resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} + engines: {node: '>=10'} + dependencies: + ansi-styles: 4.3.0 + supports-color: 7.2.0 + dev: false + + /chalk@5.3.0: + resolution: {integrity: sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==} + engines: {node: ^12.17.0 || ^14.13 || >=16.0.0} + dev: false + + /chardet@0.7.0: + resolution: {integrity: sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==} + dev: false + + /cipher-base@1.0.4: + resolution: {integrity: sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==} + dependencies: + inherits: 2.0.4 + safe-buffer: 5.2.1 + dev: false + + /cli-cursor@3.1.0: + resolution: {integrity: sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==} + engines: {node: '>=8'} + dependencies: + restore-cursor: 3.1.0 + dev: false + + /cli-spinners@2.9.2: + resolution: {integrity: sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==} + engines: {node: '>=6'} + dev: false + + /cli-width@3.0.0: + resolution: {integrity: sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==} + engines: {node: '>= 10'} + dev: false + + /clone@1.0.4: + resolution: {integrity: sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==} + engines: {node: '>=0.8'} + dev: false + + /color-convert@2.0.1: + resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} + engines: {node: '>=7.0.0'} + dependencies: + color-name: 1.1.4 + dev: false + + /color-name@1.1.4: + resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} + dev: false + + /combined-stream@1.0.8: + resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==} + engines: {node: '>= 0.8'} + dependencies: + delayed-stream: 1.0.0 + dev: false + + /commander@12.0.0: + resolution: {integrity: sha512-MwVNWlYjDTtOjX5PiD7o5pK0UrFU/OYgcJfjjK4RaHZETNtjJqrZa9Y9ds88+A+f+d5lv+561eZ+yCKoS3gbAA==} + engines: {node: '>=18'} + dev: false + + /commander@2.20.3: + resolution: {integrity: sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==} + dev: false + + /commander@8.3.0: + resolution: {integrity: sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==} + engines: {node: '>= 12'} + dev: false + + /create-hash@1.2.0: + resolution: {integrity: sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==} + dependencies: + cipher-base: 1.0.4 + inherits: 2.0.4 + md5.js: 1.3.5 + ripemd160: 2.0.2 + sha.js: 2.4.11 + dev: false + + /create-hmac@1.1.7: + resolution: {integrity: sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==} + dependencies: + cipher-base: 1.0.4 + create-hash: 1.2.0 + inherits: 2.0.4 + ripemd160: 2.0.2 + safe-buffer: 5.2.1 + sha.js: 2.4.11 + dev: false + + /cross-fetch@3.1.8: + resolution: {integrity: sha512-cvA+JwZoU0Xq+h6WkMvAUqPEYy92Obet6UdKLfW60qn99ftItKjB5T+BkyWOFWe2pUyfQ+IJHmpOTznqk1M6Kg==} + dependencies: + node-fetch: 2.7.0 + transitivePeerDependencies: + - encoding + dev: false + + /crypto-js@4.2.0: + resolution: {integrity: sha512-KALDyEYgpY+Rlob/iriUtjV6d5Eq+Y191A5g4UqLAi8CyGP9N1+FdVbkc1SxKc2r4YAYqG8JzO2KGL+AizD70Q==} + dev: false + + /csv-generate@3.4.3: + resolution: {integrity: sha512-w/T+rqR0vwvHqWs/1ZyMDWtHHSJaN06klRqJXBEpDJaM/+dZkso0OKh1VcuuYvK3XM53KysVNq8Ko/epCK8wOw==} + dev: false + + /csv-parse@4.16.3: + resolution: {integrity: sha512-cO1I/zmz4w2dcKHVvpCr7JVRu8/FymG5OEpmvsZYlccYolPBLoVGKUHgNoc4ZGkFeFlWGEDmMyBM+TTqRdW/wg==} + dev: false + + /csv-stringify@5.6.5: + resolution: {integrity: sha512-PjiQ659aQ+fUTQqSrd1XEDnOr52jh30RBurfzkscaE2tPaFsDH5wOAHJiw8XAHphRknCwMUE9KRayc4K/NbO8A==} + dev: false + + /csv@5.5.3: + resolution: {integrity: sha512-QTaY0XjjhTQOdguARF0lGKm5/mEq9PD9/VhZZegHDIBq2tQwgNpHc3dneD4mGo2iJs+fTKv5Bp0fZ+BRuY3Z0g==} + engines: {node: '>= 0.1.90'} + dependencies: + csv-generate: 3.4.3 + csv-parse: 4.16.3 + csv-stringify: 5.6.5 + stream-transform: 2.1.3 + dev: false + + /debug@4.3.4: + resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==} + engines: {node: '>=6.0'} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + dependencies: + ms: 2.1.2 + dev: false + + /defaults@1.0.4: + resolution: {integrity: sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==} + dependencies: + clone: 1.0.4 + dev: false + + /define-data-property@1.1.4: + resolution: {integrity: sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==} + engines: {node: '>= 0.4'} + dependencies: + es-define-property: 1.0.0 + es-errors: 1.3.0 + gopd: 1.0.1 + dev: false + + /delay@5.0.0: + resolution: {integrity: sha512-ReEBKkIfe4ya47wlPYf/gu5ib6yUG0/Aez0JQZQz94kiWtRQvZIQbTiehsnwHvLSWJnQdhVeqYue7Id1dKr0qw==} + engines: {node: '>=10'} + dev: false + + /delayed-stream@1.0.0: + resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} + engines: {node: '>=0.4.0'} + dev: false + + /depd@1.1.2: + resolution: {integrity: sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==} + engines: {node: '>= 0.6'} + dev: false + + /depd@2.0.0: + resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==} + engines: {node: '>= 0.8'} + dev: false + + /dotenv@10.0.0: + resolution: {integrity: sha512-rlBi9d8jpv9Sf1klPjNfFAuWDjKLwTIJJ/VxtoTwIR6hnZxcEOQCZg2oIL3MWBYw5GpUDKOEnND7LXTbIpQ03Q==} + engines: {node: '>=10'} + dev: false + + /elliptic@6.5.4: + resolution: {integrity: sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ==} + dependencies: + bn.js: 4.12.0 + brorand: 1.1.0 + hash.js: 1.1.7 + hmac-drbg: 1.0.1 + inherits: 2.0.4 + minimalistic-assert: 1.0.1 + minimalistic-crypto-utils: 1.0.1 + dev: false + + /elliptic@6.5.5: + resolution: {integrity: sha512-7EjbcmUm17NQFu4Pmgmq2olYMj8nwMnpcddByChSUjArp8F5DQWcIcpriwO4ZToLNAJig0yiyjswfyGNje/ixw==} + dependencies: + bn.js: 4.12.0 + brorand: 1.1.0 + hash.js: 1.1.7 + hmac-drbg: 1.0.1 + inherits: 2.0.4 + minimalistic-assert: 1.0.1 + minimalistic-crypto-utils: 1.0.1 + dev: false + + /emoji-regex@8.0.0: + resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} + dev: false + + /es-define-property@1.0.0: + resolution: {integrity: sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==} + engines: {node: '>= 0.4'} + dependencies: + get-intrinsic: 1.2.4 + dev: false + + /es-errors@1.3.0: + resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==} + engines: {node: '>= 0.4'} + dev: false + + /es6-promise@4.2.8: + resolution: {integrity: sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==} + dev: false + + /es6-promisify@5.0.0: + resolution: {integrity: sha512-C+d6UdsYDk0lMebHNR4S2NybQMMngAOnOwYBQjTOiv0MkoJMP0Myw2mgpDLBcpfCmRLxyFqYhS/CfOENq4SJhQ==} + dependencies: + es6-promise: 4.2.8 + dev: false + + /escape-string-regexp@1.0.5: + resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==} + engines: {node: '>=0.8.0'} + dev: false + + /ethereum-bloom-filters@1.1.0: + resolution: {integrity: sha512-J1gDRkLpuGNvWYzWslBQR9cDV4nd4kfvVTE/Wy4Kkm4yb3EYRSlyi0eB/inTsSTTVyA0+HyzHgbr95Fn/Z1fSw==} + dependencies: + '@noble/hashes': 1.4.0 + dev: false + + /ethereum-cryptography@2.1.3: + resolution: {integrity: sha512-BlwbIL7/P45W8FGW2r7LGuvoEZ+7PWsniMvQ4p5s2xCyw9tmaDlpfsN9HjAucbF+t/qpVHwZUisgfK24TCW8aA==} + dependencies: + '@noble/curves': 1.3.0 + '@noble/hashes': 1.3.3 + '@scure/bip32': 1.3.3 + '@scure/bip39': 1.2.2 + dev: false + + /ethjs-unit@0.1.6: + resolution: {integrity: sha512-/Sn9Y0oKl0uqQuvgFk/zQgR7aw1g36qX/jzSQ5lSwlO0GigPymk4eGQfeNTD03w1dPOqfz8V77Cy43jH56pagw==} + engines: {node: '>=6.5.0', npm: '>=3'} + dependencies: + bn.js: 4.11.6 + number-to-bn: 1.7.0 + dev: false + + /eventemitter3@4.0.7: + resolution: {integrity: sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==} + dev: false + + /eventemitter3@5.0.1: + resolution: {integrity: sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==} + dev: false + + /exponential-backoff@3.1.1: + resolution: {integrity: sha512-dX7e/LHVJ6W3DE1MHWi9S1EYzDESENfLrYohG2G++ovZrYOkm4Knwa0mc1cn84xJOR4KEU0WSchhLbd0UklbHw==} + requiresBuild: true + dev: false + optional: true + + /external-editor@3.1.0: + resolution: {integrity: sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==} + engines: {node: '>=4'} + dependencies: + chardet: 0.7.0 + iconv-lite: 0.4.24 + tmp: 0.0.33 + dev: false + + /eyes@0.1.8: + resolution: {integrity: sha512-GipyPsXO1anza0AOZdy69Im7hGFCNB7Y/NGjDlZGJ3GJJLtwNSb2vrzYrTYJRrRloVx7pl+bhUaTB8yiccPvFQ==} + engines: {node: '> 0.1.90'} + dev: false + + /fast-stable-stringify@1.0.0: + resolution: {integrity: sha512-wpYMUmFu5f00Sm0cj2pfivpmawLZ0NKdviQ4w9zJeR8JVtOpOxHmLaJuj0vxvGqMJQWyP/COUkF75/57OKyRag==} + dev: false + + /fastestsmallesttextencoderdecoder@1.0.22: + resolution: {integrity: sha512-Pb8d48e+oIuY4MaM64Cd7OW1gt4nxCHs7/ddPPZ/Ic3sg8yVGM7O9wDvZ7us6ScaUupzM+pfBolwtYhN1IxBIw==} + dev: false + + /figures@3.2.0: + resolution: {integrity: sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==} + engines: {node: '>=8'} + dependencies: + escape-string-regexp: 1.0.5 + dev: false + + /file-uri-to-path@1.0.0: + resolution: {integrity: sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==} + dev: false + + /follow-redirects@1.15.6(debug@4.3.4): + resolution: {integrity: sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==} + engines: {node: '>=4.0'} + peerDependencies: + debug: '*' + peerDependenciesMeta: + debug: + optional: true + dependencies: + debug: 4.3.4 + dev: false + + /for-each@0.3.3: + resolution: {integrity: sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==} + dependencies: + is-callable: 1.2.7 + dev: false + + /form-data@4.0.0: + resolution: {integrity: sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==} + engines: {node: '>= 6'} + dependencies: + asynckit: 0.4.0 + combined-stream: 1.0.8 + mime-types: 2.1.35 + dev: false + + /function-bind@1.1.2: + resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} + dev: false + + /get-intrinsic@1.2.4: + resolution: {integrity: sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==} + engines: {node: '>= 0.4'} + dependencies: + es-errors: 1.3.0 + function-bind: 1.1.2 + has-proto: 1.0.3 + has-symbols: 1.0.3 + hasown: 2.0.2 + dev: false + + /gopd@1.0.1: + resolution: {integrity: sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==} + dependencies: + get-intrinsic: 1.2.4 + dev: false + + /has-flag@4.0.0: + resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} + engines: {node: '>=8'} + dev: false + + /has-property-descriptors@1.0.2: + resolution: {integrity: sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==} + dependencies: + es-define-property: 1.0.0 + dev: false + + /has-proto@1.0.3: + resolution: {integrity: sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==} + engines: {node: '>= 0.4'} + dev: false + + /has-symbols@1.0.3: + resolution: {integrity: sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==} + engines: {node: '>= 0.4'} + dev: false + + /has-tostringtag@1.0.2: + resolution: {integrity: sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==} + engines: {node: '>= 0.4'} + dependencies: + has-symbols: 1.0.3 + dev: false + + /hash-base@3.1.0: + resolution: {integrity: sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA==} + engines: {node: '>=4'} + dependencies: + inherits: 2.0.4 + readable-stream: 3.6.2 + safe-buffer: 5.2.1 + dev: false + + /hash.js@1.1.7: + resolution: {integrity: sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==} + dependencies: + inherits: 2.0.4 + minimalistic-assert: 1.0.1 + dev: false + + /hasown@2.0.2: + resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} + engines: {node: '>= 0.4'} + dependencies: + function-bind: 1.1.2 + dev: false + + /hi-base32@0.5.1: + resolution: {integrity: sha512-EmBBpvdYh/4XxsnUybsPag6VikPYnN30td+vQk+GI3qpahVEG9+gTkG0aXVxTjBqQ5T6ijbWIu77O+C5WFWsnA==} + dev: false + + /hmac-drbg@1.0.1: + resolution: {integrity: sha512-Tti3gMqLdZfhOQY1Mzf/AanLiqh1WTiJgEj26ZuYQ9fbkLomzGchCws4FyrSd4VkpBfiNhaE1On+lOz894jvXg==} + dependencies: + hash.js: 1.1.7 + minimalistic-assert: 1.0.1 + minimalistic-crypto-utils: 1.0.1 + dev: false + + /http-errors@1.8.1: + resolution: {integrity: sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g==} + engines: {node: '>= 0.6'} + dependencies: + depd: 1.1.2 + inherits: 2.0.4 + setprototypeof: 1.2.0 + statuses: 1.5.0 + toidentifier: 1.0.1 + dev: false + + /humanize-ms@1.2.1: + resolution: {integrity: sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==} + dependencies: + ms: 2.1.3 + dev: false + + /iconv-lite@0.4.24: + resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==} + engines: {node: '>=0.10.0'} + dependencies: + safer-buffer: 2.1.2 + dev: false + + /ieee754@1.2.1: + resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} + dev: false + + /inherits@2.0.4: + resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} + dev: false + + /inquirer@8.2.6: + resolution: {integrity: sha512-M1WuAmb7pn9zdFRtQYk26ZBoY043Sse0wVDdk4Bppr+JOXyQYybdtvK+l9wUibhtjdjvtoiNy8tk+EgsYIUqKg==} + engines: {node: '>=12.0.0'} + dependencies: + ansi-escapes: 4.3.2 + chalk: 4.1.2 + cli-cursor: 3.1.0 + cli-width: 3.0.0 + external-editor: 3.1.0 + figures: 3.2.0 + lodash: 4.17.21 + mute-stream: 0.0.8 + ora: 5.4.1 + run-async: 2.4.1 + rxjs: 7.8.1 + string-width: 4.2.3 + strip-ansi: 6.0.1 + through: 2.3.8 + wrap-ansi: 6.2.0 + dev: false + + /is-arguments@1.1.1: + resolution: {integrity: sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.7 + has-tostringtag: 1.0.2 + dev: false + + /is-callable@1.2.7: + resolution: {integrity: sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==} + engines: {node: '>= 0.4'} + dev: false + + /is-fullwidth-code-point@3.0.0: + resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} + engines: {node: '>=8'} + dev: false + + /is-generator-function@1.0.10: + resolution: {integrity: sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==} + engines: {node: '>= 0.4'} + dependencies: + has-tostringtag: 1.0.2 + dev: false + + /is-hex-prefixed@1.0.0: + resolution: {integrity: sha512-WvtOiug1VFrE9v1Cydwm+FnXd3+w9GaeVUss5W4v/SLy3UW00vP+6iNF2SdnfiBoLy4bTqVdkftNGTUeOFVsbA==} + engines: {node: '>=6.5.0', npm: '>=3'} + dev: false + + /is-interactive@1.0.0: + resolution: {integrity: sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==} + engines: {node: '>=8'} + dev: false + + /is-typed-array@1.1.13: + resolution: {integrity: sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw==} + engines: {node: '>= 0.4'} + dependencies: + which-typed-array: 1.1.15 + dev: false + + /is-unicode-supported@0.1.0: + resolution: {integrity: sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==} + engines: {node: '>=10'} + dev: false + + /isomorphic-ws@4.0.1(ws@7.5.9): + resolution: {integrity: sha512-BhBvN2MBpWTaSHdWRb/bwdZJ1WaehQ2L1KngkCkfLUGF0mAWAT1sQUQacEmQ0jXkFw/czDXPNQSL5u2/Krsz1w==} + peerDependencies: + ws: '*' + dependencies: + ws: 7.5.9 + dev: false + + /jayson@4.1.0: + resolution: {integrity: sha512-R6JlbyLN53Mjku329XoRT2zJAE6ZgOQ8f91ucYdMCD4nkGCF9kZSrcGXpHIU4jeKj58zUZke2p+cdQchU7Ly7A==} + engines: {node: '>=8'} + hasBin: true + dependencies: + '@types/connect': 3.4.38 + '@types/node': 12.20.55 + '@types/ws': 7.4.7 + 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(ws@7.5.9) + json-stringify-safe: 5.0.1 + uuid: 8.3.2 + ws: 7.5.9 + transitivePeerDependencies: + - bufferutil + - utf-8-validate + dev: false + + /js-sha256@0.9.0: + resolution: {integrity: sha512-sga3MHh9sgQN2+pJ9VYZ+1LPwXOxuBJBA5nrR5/ofPfuiJBE2hnjsaN8se8JznOmGLN2p49Pe5U/ttafcs/apA==} + dev: false + + /js-sha3@0.8.0: + resolution: {integrity: sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q==} + dev: false + + /js-sha512@0.8.0: + resolution: {integrity: sha512-PWsmefG6Jkodqt+ePTvBZCSMFgN7Clckjd0O7su3I0+BW2QWUTJNzjktHsztGLhncP2h8mcF9V9Y2Ha59pAViQ==} + dev: false + + /json-bigint@1.0.0: + resolution: {integrity: sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ==} + dependencies: + bignumber.js: 9.1.2 + dev: false + + /json-stringify-safe@5.0.1: + resolution: {integrity: sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==} + dev: false + + /jsonparse@1.3.1: + resolution: {integrity: sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg==} + engines: {'0': node >= 0.2.0} + dev: false + + /keccak@3.0.4: + resolution: {integrity: sha512-3vKuW0jV8J3XNTzvfyicFR5qvxrSAGl7KIhvgOu5cmWwM7tZRj3fMbj/pfIf4be7aznbc+prBWGjywox/g2Y6Q==} + engines: {node: '>=10.0.0'} + requiresBuild: true + dependencies: + node-addon-api: 2.0.2 + node-gyp-build: 4.8.1 + readable-stream: 3.6.2 + dev: false + + /lodash.clonedeep@4.5.0: + resolution: {integrity: sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ==} + dev: false + + /lodash.isequal@4.5.0: + resolution: {integrity: sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==} + dev: false + + /lodash@4.17.21: + resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} + dev: false + + /log-symbols@4.1.0: + resolution: {integrity: sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==} + engines: {node: '>=10'} + dependencies: + chalk: 4.1.2 + is-unicode-supported: 0.1.0 + dev: false + + /md5.js@1.3.5: + resolution: {integrity: sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==} + dependencies: + hash-base: 3.1.0 + inherits: 2.0.4 + safe-buffer: 5.2.1 + dev: false + + /merkletreejs@0.3.11: + resolution: {integrity: sha512-LJKTl4iVNTndhL+3Uz/tfkjD0klIWsHlUzgtuNnNrsf7bAlXR30m+xYB7lHr5Z/l6e/yAIsr26Dabx6Buo4VGQ==} + engines: {node: '>= 7.6.0'} + dependencies: bignumber.js: 9.1.2 - web3-utils: 4.2.1 - ws: 8.16.0 - transitivePeerDependencies: - - bufferutil - - utf-8-validate + buffer-reverse: 1.0.1 + crypto-js: 4.2.0 + treeify: 1.1.0 + web3-utils: 1.10.4 dev: false - /@noble/curves@1.3.0: - resolution: {integrity: sha512-t01iSXPuN+Eqzb4eBX0S5oubSqXbK/xXa1Ne18Hj8f9pStxztHCE2gfboSp/dZRLSqfuLpRK2nDXDK+W9puocA==} + /micro-ftch@0.3.1: + resolution: {integrity: sha512-/0LLxhzP0tfiR5hcQebtudP56gUurs2CLkGarnCiB/OqEyUFQ6U3paQi/tgLv0hBJYt2rnr9MNpxz4fiiugstg==} + dev: false + + /mime-db@1.52.0: + resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} + engines: {node: '>= 0.6'} + dev: false + + /mime-types@2.1.35: + resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} + engines: {node: '>= 0.6'} dependencies: - '@noble/hashes': 1.3.3 + mime-db: 1.52.0 dev: false - /@noble/hashes@1.3.3: - resolution: {integrity: sha512-V7/fPHgl+jsVPXqqeOzT8egNj2iBIVt+ECeMMG8TdcnTikP3oaBtUVqpT/gYCR68aEBJSF+XbYUxStjbFMqIIA==} - engines: {node: '>= 16'} + /mime@3.0.0: + resolution: {integrity: sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A==} + engines: {node: '>=10.0.0'} + hasBin: true dev: false - /@scure/base@1.1.6: - resolution: {integrity: sha512-ok9AWwhcgYuGG3Zfhyqg+zwl+Wn5uE+dwC0NV/2qQkx4dABbb/bx96vWu8NSj+BNjjSjno+JRYRjle1jV08k3g==} + /mimic-fn@2.1.0: + resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==} + engines: {node: '>=6'} dev: false - /@scure/bip32@1.3.3: - resolution: {integrity: sha512-LJaN3HwRbfQK0X1xFSi0Q9amqOgzQnnDngIt+ZlsBC3Bm7/nE7K0kwshZHyaru79yIVRv/e1mQAjZyuZG6jOFQ==} - dependencies: - '@noble/curves': 1.3.0 - '@noble/hashes': 1.3.3 - '@scure/base': 1.1.6 + /minimalistic-assert@1.0.1: + resolution: {integrity: sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==} dev: false - /@scure/bip39@1.2.2: - resolution: {integrity: sha512-HYf9TUXG80beW+hGAt3TRM8wU6pQoYur9iNypTROm42dorCGmLnFe3eWjz3gOq6G62H2WRh0FCzAR1PI+29zIA==} - dependencies: - '@noble/hashes': 1.3.3 - '@scure/base': 1.1.6 + /minimalistic-crypto-utils@1.0.1: + resolution: {integrity: sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg==} dev: false - /@types/node@20.12.7: - resolution: {integrity: sha512-wq0cICSkRLVaf3UGLMGItu/PtdY7oaXaI/RVU+xliKVOtRna3PRY57ZDfztpDL0n11vfymMUnXv8QwYCO7L1wg==} - dependencies: - undici-types: 5.26.5 + /mixme@0.5.10: + resolution: {integrity: sha512-5H76ANWinB1H3twpJ6JY8uvAtpmFvHNArpilJAjXRKXSDDLPIMoZArw5SH0q9z+lLs8IrMw7Q2VWpWimFKFT1Q==} + engines: {node: '>= 8.0.0'} dev: false - /@types/ws@8.5.10: - resolution: {integrity: sha512-vmQSUcfalpIq0R9q7uTo2lXs6eGIpt9wtnLdMv9LVpIjCA/+ufZRozlVoVelIYixx1ugCBKDhn89vnsEGOCx9A==} - dependencies: - '@types/node': 20.12.7 + /ms@2.1.2: + resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==} dev: false - /available-typed-arrays@1.0.7: - resolution: {integrity: sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==} - engines: {node: '>= 0.4'} + /ms@2.1.3: + resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} + dev: false + + /multistream@4.1.0: + resolution: {integrity: sha512-J1XDiAmmNpRCBfIWJv+n0ymC4ABcf/Pl+5YvC5B/D2f/2+8PtHvCNxMPKiQcZyi922Hq69J2YOpb1pTywfifyw==} + requiresBuild: true dependencies: - possible-typed-array-names: 1.0.0 + once: 1.4.0 + readable-stream: 3.6.2 dev: false + optional: true - /bignumber.js@9.1.2: - resolution: {integrity: sha512-2/mKyZH9K85bzOEfhXDBFZTGd1CTs+5IHpeFQo9luiBG7hghdC851Pj2WAhb6E3R6b9tZj/XKhbg4fum+Kepug==} + /mustache@4.2.0: + resolution: {integrity: sha512-71ippSywq5Yb7/tVYyGbkBggbU8H3u5Rz56fH60jGFgr8uHwxs+aSKeqmluIVzM0m0kB7xQjKS6qPfd0b2ZoqQ==} + hasBin: true dev: false - /call-bind@1.0.7: - resolution: {integrity: sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==} - engines: {node: '>= 0.4'} - dependencies: - es-define-property: 1.0.0 - es-errors: 1.3.0 - function-bind: 1.1.2 - get-intrinsic: 1.2.4 - set-function-length: 1.2.2 + /mute-stream@0.0.8: + resolution: {integrity: sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==} dev: false - /define-data-property@1.1.4: - resolution: {integrity: sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==} - engines: {node: '>= 0.4'} + /near-hd-key@1.2.1: + resolution: {integrity: sha512-SIrthcL5Wc0sps+2e1xGj3zceEa68TgNZDLuCx0daxmfTP7sFTB3/mtE2pYhlFsCxWoMn+JfID5E1NlzvvbRJg==} dependencies: - es-define-property: 1.0.0 - es-errors: 1.3.0 - gopd: 1.0.1 + bip39: 3.0.2 + create-hmac: 1.1.7 + tweetnacl: 1.0.3 dev: false - /es-define-property@1.0.0: - resolution: {integrity: sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==} - engines: {node: '>= 0.4'} + /near-seed-phrase@0.2.0: + resolution: {integrity: sha512-NpmrnejpY1AdlRpDZ0schJQJtfBaoUheRfiYtQpcq9TkwPgqKZCRULV5L3hHmLc0ep7KRtikbPQ9R2ztN/3cyQ==} dependencies: - get-intrinsic: 1.2.4 + bip39-light: 1.0.7 + bs58: 4.0.1 + near-hd-key: 1.2.1 + tweetnacl: 1.0.3 dev: false - /es-errors@1.3.0: - resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==} - engines: {node: '>= 0.4'} + /node-addon-api@2.0.2: + resolution: {integrity: sha512-Ntyt4AIXyaLIuMHF6IOoTakB3K+RWxwtsHNRxllEoA6vPwP9o4866g6YWDLUdnucilZhmkxiHwHr11gAENw+QA==} dev: false - /ethereum-cryptography@2.1.3: - resolution: {integrity: sha512-BlwbIL7/P45W8FGW2r7LGuvoEZ+7PWsniMvQ4p5s2xCyw9tmaDlpfsN9HjAucbF+t/qpVHwZUisgfK24TCW8aA==} + /node-addon-api@5.1.0: + resolution: {integrity: sha512-eh0GgfEkpnoWDq+VY8OyvYhFEzBk6jIYbRKdIlyTiAXIVJ8PyBaKb0rp7oDtoddbdoHWhq8wwr+XZ81F1rpNdA==} + dev: false + + /node-fetch@2.7.0: + resolution: {integrity: sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==} + engines: {node: 4.x || >=6.0.0} + peerDependencies: + encoding: ^0.1.0 + peerDependenciesMeta: + encoding: + optional: true dependencies: - '@noble/curves': 1.3.0 - '@noble/hashes': 1.3.3 - '@scure/bip32': 1.3.3 - '@scure/bip39': 1.2.2 + whatwg-url: 5.0.0 dev: false - /eventemitter3@5.0.1: - resolution: {integrity: sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==} + /node-gyp-build@4.8.1: + resolution: {integrity: sha512-OSs33Z9yWr148JZcbZd5WiAXhh/n9z8TxQcdMhIOlpN9AhWpLfvVFO73+m77bBABQMaY9XSvIa+qk0jlI7Gcaw==} + hasBin: true + requiresBuild: true dev: false - /for-each@0.3.3: - resolution: {integrity: sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==} + /number-to-bn@1.7.0: + resolution: {integrity: sha512-wsJ9gfSz1/s4ZsJN01lyonwuxA1tml6X1yBDnfpMglypcBRFZZkus26EdPSlqS5GJfYddVZa22p3VNb3z5m5Ig==} + engines: {node: '>=6.5.0', npm: '>=3'} dependencies: - is-callable: 1.2.7 + bn.js: 4.11.6 + strip-hex-prefix: 1.0.0 dev: false - /function-bind@1.1.2: - resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} + /once@1.4.0: + resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} + requiresBuild: true + dependencies: + wrappy: 1.0.2 dev: false + optional: true - /get-intrinsic@1.2.4: - resolution: {integrity: sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==} - engines: {node: '>= 0.4'} + /onetime@5.1.2: + resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==} + engines: {node: '>=6'} dependencies: - es-errors: 1.3.0 - function-bind: 1.1.2 - has-proto: 1.0.3 - has-symbols: 1.0.3 - hasown: 2.0.2 + mimic-fn: 2.1.0 dev: false - /gopd@1.0.1: - resolution: {integrity: sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==} + /ora@5.4.1: + resolution: {integrity: sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==} + engines: {node: '>=10'} dependencies: - get-intrinsic: 1.2.4 + bl: 4.1.0 + chalk: 4.1.2 + cli-cursor: 3.1.0 + cli-spinners: 2.9.2 + is-interactive: 1.0.0 + is-unicode-supported: 0.1.0 + log-symbols: 4.1.0 + strip-ansi: 6.0.1 + wcwidth: 1.0.1 dev: false - /has-property-descriptors@1.0.2: - resolution: {integrity: sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==} + /os-tmpdir@1.0.2: + resolution: {integrity: sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==} + engines: {node: '>=0.10.0'} + dev: false + + /pbkdf2@3.1.2: + resolution: {integrity: sha512-iuh7L6jA7JEGu2WxDwtQP1ddOpaJNC4KlDEFfdQajSGgGPNi4OyDc2R7QnbY2bR9QjBVGwgvTdNJZoE7RaxUMA==} + engines: {node: '>=0.12'} dependencies: - es-define-property: 1.0.0 + create-hash: 1.2.0 + create-hmac: 1.1.7 + ripemd160: 2.0.2 + safe-buffer: 5.2.1 + sha.js: 2.4.11 dev: false - /has-proto@1.0.3: - resolution: {integrity: sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==} + /possible-typed-array-names@1.0.0: + resolution: {integrity: sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==} engines: {node: '>= 0.4'} dev: false - /has-symbols@1.0.3: - resolution: {integrity: sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==} - engines: {node: '>= 0.4'} + /proxy-from-env@1.1.0: + resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==} dev: false - /has-tostringtag@1.0.2: - resolution: {integrity: sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==} - engines: {node: '>= 0.4'} + /randombytes@2.1.0: + resolution: {integrity: sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==} dependencies: - has-symbols: 1.0.3 + safe-buffer: 5.2.1 dev: false - /hasown@2.0.2: - resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} - engines: {node: '>= 0.4'} + /readable-stream@3.6.2: + resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==} + engines: {node: '>= 6'} dependencies: - function-bind: 1.1.2 + inherits: 2.0.4 + string_decoder: 1.3.0 + util-deprecate: 1.0.2 dev: false - /inherits@2.0.4: - resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} + /regenerator-runtime@0.14.1: + resolution: {integrity: sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==} dev: false - /is-arguments@1.1.1: - resolution: {integrity: sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==} - engines: {node: '>= 0.4'} + /restore-cursor@3.1.0: + resolution: {integrity: sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==} + engines: {node: '>=8'} dependencies: - call-bind: 1.0.7 - has-tostringtag: 1.0.2 + onetime: 5.1.2 + signal-exit: 3.0.7 dev: false - /is-callable@1.2.7: - resolution: {integrity: sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==} - engines: {node: '>= 0.4'} + /retry@0.13.1: + resolution: {integrity: sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==} + engines: {node: '>= 4'} dev: false - /is-generator-function@1.0.10: - resolution: {integrity: sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==} - engines: {node: '>= 0.4'} + /ripemd160@2.0.2: + resolution: {integrity: sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==} dependencies: - has-tostringtag: 1.0.2 + hash-base: 3.1.0 + inherits: 2.0.4 dev: false - /is-typed-array@1.1.13: - resolution: {integrity: sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw==} - engines: {node: '>= 0.4'} + /rpc-websockets@7.11.0: + resolution: {integrity: sha512-IkLYjayPv6Io8C/TdCL5gwgzd1hFz2vmBZrjMw/SPEXo51ETOhnzgS4Qy5GWi2JQN7HKHa66J3+2mv0fgNh/7w==} dependencies: - which-typed-array: 1.1.15 + eventemitter3: 4.0.7 + uuid: 8.3.2 + ws: 8.16.0(bufferutil@4.0.8)(utf-8-validate@5.0.10) + optionalDependencies: + bufferutil: 4.0.8 + utf-8-validate: 5.0.10 dev: false - /possible-typed-array-names@1.0.0: - resolution: {integrity: sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==} - engines: {node: '>= 0.4'} + /run-async@2.4.1: + resolution: {integrity: sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==} + engines: {node: '>=0.12.0'} + dev: false + + /rxjs@7.8.1: + resolution: {integrity: sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==} + dependencies: + tslib: 2.6.2 + dev: false + + /safe-buffer@5.2.1: + resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} + dev: false + + /safer-buffer@2.1.2: + resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} + dev: false + + /scrypt-js@3.0.1: + resolution: {integrity: sha512-cdwTTnqPu0Hyvf5in5asVdZocVDTNRmR7XEcJuIzMjJeSHybHl7vpB66AzwTaIg6CLSbtjcxc8fqcySfnTkccA==} + dev: false + + /secp256k1@5.0.0: + resolution: {integrity: sha512-TKWX8xvoGHrxVdqbYeZM9w+izTF4b9z3NhSaDkdn81btvuh+ivbIMGT/zQvDtTFWhRlThpoz6LEYTr7n8A5GcA==} + engines: {node: '>=14.0.0'} + requiresBuild: true + dependencies: + elliptic: 6.5.5 + node-addon-api: 5.1.0 + node-gyp-build: 4.8.1 dev: false /set-function-length@1.2.2: @@ -233,10 +2292,154 @@ packages: has-property-descriptors: 1.0.2 dev: false + /setprototypeof@1.2.0: + resolution: {integrity: sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==} + dev: false + + /sha.js@2.4.11: + resolution: {integrity: sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==} + hasBin: true + dependencies: + inherits: 2.0.4 + safe-buffer: 5.2.1 + dev: false + + /signal-exit@3.0.7: + resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==} + dev: false + + /statuses@1.5.0: + resolution: {integrity: sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==} + engines: {node: '>= 0.6'} + dev: false + + /stream-transform@2.1.3: + resolution: {integrity: sha512-9GHUiM5hMiCi6Y03jD2ARC1ettBXkQBoQAe7nJsPknnI0ow10aXjTnew8QtYQmLjzn974BnmWEAJgCY6ZP1DeQ==} + dependencies: + mixme: 0.5.10 + dev: false + + /string-width@4.2.3: + resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} + engines: {node: '>=8'} + dependencies: + emoji-regex: 8.0.0 + is-fullwidth-code-point: 3.0.0 + strip-ansi: 6.0.1 + dev: false + + /string_decoder@1.3.0: + resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==} + dependencies: + safe-buffer: 5.2.1 + dev: false + + /strip-ansi@6.0.1: + resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} + engines: {node: '>=8'} + dependencies: + ansi-regex: 5.0.1 + dev: false + + /strip-hex-prefix@1.0.0: + resolution: {integrity: sha512-q8d4ue7JGEiVcypji1bALTos+0pWtyGlivAWyPuTkHzuTCJqrK9sWxYQZUq6Nq3cuyv3bm734IhHvHtGGURU6A==} + engines: {node: '>=6.5.0', npm: '>=3'} + dependencies: + is-hex-prefixed: 1.0.0 + dev: false + + /superstruct@0.14.2: + resolution: {integrity: sha512-nPewA6m9mR3d6k7WkZ8N8zpTWfenFH3q9pA2PkuiZxINr9DKB2+40wEQf0ixn8VaGuJ78AB6iWOtStI+/4FKZQ==} + dev: false + + /supports-color@7.2.0: + resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} + engines: {node: '>=8'} + dependencies: + has-flag: 4.0.0 + dev: false + + /text-encoding-utf-8@1.0.2: + resolution: {integrity: sha512-8bw4MY9WjdsD2aMtO0OzOCY3pXGYNx2d2FfHRVUKkiCPDWjKuOlhLVASS+pD7VkLTVjW268LYJHwsnPFlBpbAg==} + dev: false + + /through@2.3.8: + resolution: {integrity: sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==} + dev: false + + /tmp-promise@3.0.3: + resolution: {integrity: sha512-RwM7MoPojPxsOBYnyd2hy0bxtIlVrihNs9pj5SUvY8Zz1sQcQG2tG1hSr8PDxfgEB8RNKDhqbIlroIarSNDNsQ==} + requiresBuild: true + dependencies: + tmp: 0.2.3 + dev: false + optional: true + + /tmp@0.0.33: + resolution: {integrity: sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==} + engines: {node: '>=0.6.0'} + dependencies: + os-tmpdir: 1.0.2 + dev: false + + /tmp@0.2.3: + resolution: {integrity: sha512-nZD7m9iCPC5g0pYmcaxogYKggSfLsdxl8of3Q/oIbqCqLLIO9IAF0GWjX1z9NZRHPiXv8Wex4yDCaZsgEw0Y8w==} + engines: {node: '>=14.14'} + requiresBuild: true + dev: false + optional: true + + /toidentifier@1.0.1: + resolution: {integrity: sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==} + engines: {node: '>=0.6'} + dev: false + + /tr46@0.0.3: + resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==} + dev: false + + /treeify@1.1.0: + resolution: {integrity: sha512-1m4RA7xVAJrSGrrXGs0L3YTwyvBs2S8PbRHaLZAkFw7JR8oIFwYtysxlBZhYIa7xSyiYJKZ3iGrrk55cGA3i9A==} + engines: {node: '>=0.6'} + dev: false + + /tslib@2.6.2: + resolution: {integrity: sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==} + dev: false + + /tweetnacl@1.0.3: + resolution: {integrity: sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw==} + dev: false + + /type-fest@0.21.3: + resolution: {integrity: sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==} + engines: {node: '>=10'} + dev: false + + /typescript-collections@1.3.3: + resolution: {integrity: sha512-7sI4e/bZijOzyURng88oOFZCISQPTHozfE2sUu5AviFYk5QV7fYGb6YiDl+vKjF/pICA354JImBImL9XJWUvdQ==} + dev: false + /undici-types@5.26.5: resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==} dev: false + /utf-8-validate@5.0.10: + resolution: {integrity: sha512-Z6czzLq4u8fPOyx7TU6X3dvUZVvoJmxSQ+IcrlmagKhilxlhZgxPK6C5Jqbkw1IDUmFTM+cz9QDnnLTwDz/2gQ==} + engines: {node: '>=6.14.2'} + requiresBuild: true + dependencies: + node-gyp-build: 4.8.1 + dev: false + + /utf8@3.0.0: + resolution: {integrity: sha512-E8VjFIQ/TyQgp+TZfS6l8yp/xWppSAHzidGiRrqe4bK4XP9pTRyKFgGJpO3SN7zdX4DeomTrwaseCHovfpFcqQ==} + dev: false + + /util-deprecate@1.0.2: + resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} + dev: false + /util@0.12.5: resolution: {integrity: sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA==} dependencies: @@ -247,6 +2450,21 @@ packages: which-typed-array: 1.1.15 dev: false + /uuid@8.3.2: + resolution: {integrity: sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==} + hasBin: true + dev: false + + /vlq@2.0.4: + resolution: {integrity: sha512-aodjPa2wPQFkra1G8CzJBTHXhgk3EVSwxSWXNPr1fgdFLUb8kvLV1iEb6rFgasIsjP82HWI6dsb5Io26DDnasA==} + dev: false + + /wcwidth@1.0.1: + resolution: {integrity: sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==} + dependencies: + defaults: 1.0.4 + dev: false + /web3-errors@1.1.4: resolution: {integrity: sha512-WahtszSqILez+83AxGecVroyZsMuuRT+KmQp4Si5P4Rnqbczno1k748PCrZTS1J4UCPmXMG2/Vt+0Bz2zwXkwQ==} engines: {node: '>=14', npm: '>=6.12.0'} @@ -259,6 +2477,20 @@ packages: engines: {node: '>=14', npm: '>=6.12.0'} dev: false + /web3-utils@1.10.4: + resolution: {integrity: sha512-tsu8FiKJLk2PzhDl9fXbGUWTkkVXYhtTA+SmEFkKft+9BgwLxfCRpU96sWv7ICC8zixBNd3JURVoiR3dUXgP8A==} + engines: {node: '>=8.0.0'} + dependencies: + '@ethereumjs/util': 8.1.0 + bn.js: 5.2.1 + ethereum-bloom-filters: 1.1.0 + ethereum-cryptography: 2.1.3 + ethjs-unit: 0.1.6 + number-to-bn: 1.7.0 + randombytes: 2.1.0 + utf8: 3.0.0 + dev: false + /web3-utils@4.2.1: resolution: {integrity: sha512-Fk29BlEqD9Q9Cnw4pBkKw7czcXiRpsSco/BzEUl4ye0ZTSHANQFfjsfQmNm4t7uY11u6Ah+8F3tNjBeU4CA80A==} engines: {node: '>=14', npm: '>=6.12.0'} @@ -281,6 +2513,17 @@ packages: zod: 3.22.4 dev: false + /webidl-conversions@3.0.1: + resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==} + dev: false + + /whatwg-url@5.0.0: + resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==} + dependencies: + tr46: 0.0.3 + webidl-conversions: 3.0.1 + dev: false + /which-typed-array@1.1.15: resolution: {integrity: sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA==} engines: {node: '>= 0.4'} @@ -292,7 +2535,48 @@ packages: has-tostringtag: 1.0.2 dev: false - /ws@8.16.0: + /wrap-ansi@6.2.0: + resolution: {integrity: sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==} + engines: {node: '>=8'} + dependencies: + ansi-styles: 4.3.0 + string-width: 4.2.3 + strip-ansi: 6.0.1 + dev: false + + /wrappy@1.0.2: + resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} + requiresBuild: true + dev: false + optional: true + + /ws@7.4.6: + resolution: {integrity: sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A==} + engines: {node: '>=8.3.0'} + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: ^5.0.2 + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + dev: false + + /ws@7.5.9: + resolution: {integrity: sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==} + engines: {node: '>=8.3.0'} + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: ^5.0.2 + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + dev: false + + /ws@8.16.0(bufferutil@4.0.8)(utf-8-validate@5.0.10): resolution: {integrity: sha512-HS0c//TP7Ina87TfiPUz1rQzMhHrl/SG2guqRcTOIUYD2q8uhUdNHZYJUaQ8aTGPzCh+c6oawMKW35nFl1dxyQ==} engines: {node: '>=10.0.0'} peerDependencies: @@ -303,6 +2587,9 @@ packages: optional: true utf-8-validate: optional: true + dependencies: + bufferutil: 4.0.8 + utf-8-validate: 5.0.10 dev: false /zod@3.22.4: diff --git a/packages/networks/solana/src/services/Provider.ts b/packages/networks/solana/src/services/Provider.ts index d92d40d..d5645b7 100644 --- a/packages/networks/solana/src/services/Provider.ts +++ b/packages/networks/solana/src/services/Provider.ts @@ -1,8 +1,21 @@ +import axios from 'axios' import { ErrorTypeEnum, type NetworkConfigInterface, type ProviderInterface } from '@multiplechain/types' +import { Connection } from '@solana/web3.js' +import { checkWebSocket } from '@multiplechain/utils' + +export interface SolanaNodeInfoInterface { + node: string + name: string + wsUrl?: string + rpcUrl: string + explorerUrl: string +} + +export type SolanaNodeInfoListInterface = Record export class Provider implements ProviderInterface { /** @@ -10,11 +23,36 @@ export class Provider implements ProviderInterface { */ network: NetworkConfigInterface + /** + * Node list + */ + nodes: SolanaNodeInfoListInterface = { + mainnet: { + node: 'mainnet-beta', + name: 'Mainnet', + rpcUrl: 'https://api.mainnet-beta.solana.com/', + explorerUrl: 'https://solscan.io/' + }, + devnet: { + node: 'devnet', + name: 'Devnet', + rpcUrl: 'https://api.devnet.solana.com', + explorerUrl: 'https://solscan.io/' + } + } + + /** + * Node information + */ + node: SolanaNodeInfoInterface + /** * Static instance of the provider */ private static _instance: Provider + web3: Connection + /** * @param network - Network configuration of the provider */ @@ -51,7 +89,21 @@ export class Provider implements ProviderInterface { * @returns {Promise} */ async checkRpcConnection(url?: string): Promise { - return true + try { + const response = await axios.post(url ?? this.node.rpcUrl, { + jsonrpc: '2.0', + id: 1, + method: 'getEpochInfo' + }) + + if (response.status !== 200) { + return new Error(response.statusText + ': ' + JSON.stringify(response.data)) + } + + return true + } catch (error) { + return error as any + } } /** @@ -60,7 +112,17 @@ export class Provider implements ProviderInterface { * @returns {Promise} */ async checkWsConnection(url?: string): Promise { - return true + try { + const result: any = await checkWebSocket(url ?? this.node.wsUrl ?? '') + + if (result instanceof Error) { + return result + } + + return true + } catch (error) { + return error as Error + } } /** @@ -70,6 +132,10 @@ export class Provider implements ProviderInterface { update(network: NetworkConfigInterface): void { this.network = network Provider._instance = this + this.node = this.nodes[network.testnet ?? false ? 'devnet' : 'mainnet'] + this.node.rpcUrl = this.network.rpcUrl ?? this.node.rpcUrl + this.node.wsUrl = this.network.wsUrl ?? this.node.wsUrl + this.web3 = new Connection(this.node.rpcUrl, 'recent') } /** diff --git a/packages/networks/solana/tests/services.spec.ts b/packages/networks/solana/tests/services.spec.ts index 34c5579..37d09f4 100644 --- a/packages/networks/solana/tests/services.spec.ts +++ b/packages/networks/solana/tests/services.spec.ts @@ -1,7 +1,22 @@ import { describe, it, expect } from 'vitest' -describe('example', () => { - it('should work', () => { - expect(1 + 1).toBe(2) +import { provider } from './setup.ts' +import { Provider } from '../src/services/Provider.ts' + +describe('Provider', () => { + it('isTestnet', () => { + expect(provider.isTestnet()).toBe(true) + }) + + it('instance', () => { + expect(Provider.instance).toBe(provider) + }) + + it('checkRpcConnection', async () => { + expect(await provider.checkRpcConnection()).toBe(true) + }) + + it('checkWsConnection', async () => { + expect(await provider.checkWsConnection()).toBe(true) }) }) diff --git a/packages/networks/solana/tests/setup.ts b/packages/networks/solana/tests/setup.ts index 6c04b6b..42e7f45 100644 --- a/packages/networks/solana/tests/setup.ts +++ b/packages/networks/solana/tests/setup.ts @@ -6,7 +6,8 @@ try { provider = Provider.instance } catch (e) { provider = new Provider({ - testnet: true + testnet: true, + wsUrl: 'wss://alien-wild-fire.solana-devnet.quiknode.pro/ad7c4490b11cd2134e022052f0b2779acb8998ad/' }) } diff --git a/packages/networks/solana/vitest.config.ts b/packages/networks/solana/vitest.config.ts index 73ee32b..433e719 100644 --- a/packages/networks/solana/vitest.config.ts +++ b/packages/networks/solana/vitest.config.ts @@ -5,6 +5,7 @@ export default mergeConfig( mainConfig, defineConfig({ test: { + testTimeout: 180000, setupFiles: ['./tests/setup.ts'] } }) diff --git a/vitest.config.ts b/vitest.config.ts index 1e8d759..98b864d 100644 --- a/vitest.config.ts +++ b/vitest.config.ts @@ -31,6 +31,7 @@ export default mergeConfig( setupFiles: [ './packages/networks/evm-chains/tests/setup.ts', './packages/networks/bitcoin/tests/setup.ts', + './packages/networks/solana/tests/setup.ts', './packages/networks/tron/tests/setup.ts' ] } From 97a5f9b32b6a402d5d77480b94b61db123c42bdc Mon Sep 17 00:00:00 2001 From: Halil Beycan <50718965+BeycanDeveloper@users.noreply.github.com> Date: Thu, 16 May 2024 21:19:59 +0800 Subject: [PATCH 29/90] added solana env data --- .env.example | 49 ++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 44 insertions(+), 5 deletions(-) diff --git a/.env.example b/.env.example index e98f9ad..c8ad657 100644 --- a/.env.example +++ b/.env.example @@ -1,4 +1,4 @@ -# EVM CHAINS +# EVM Chains EVM_RPC_URL='https://sepolia.infura.io/v3/9aa3d95b3bc440fa88ea12eaa4456161' EVM_WS_URL='wss://sepolia.infura.io/ws/v3/9aa3d95b3bc440fa88ea12eaa4456161' @@ -43,9 +43,9 @@ EVM_ETHER_TRANSFER_TX='0x566002399664e92f82ed654c181095bdd7ff3d3f1921d9632575858 EVM_TOKEN_TRANSFER_TX='0xdabda3905e585db91768f2ef877f7fbef7c0e8612c0a09c7b379981bdbc48975' EVM_NFT_TRANSFER_TX='0x272a4698cd2062f2463481cf9eb78b68b35d59938383679b7642e6d669ac87eb' # Models -# EVM CHAINS +# EVM Chains -#TRON +#Tron # Assets TRON_COIN_TRANSFER_TEST_IS_ACTIVE=false TRON_TOKEN_TRANSFER_TEST_IS_ACTIVE=false @@ -82,7 +82,7 @@ TRON_MODEL_TEST_RECEIVER='TS1WYZNoNw32hog68m5GyhwZnkhf6HNzhi' TRON_TRX_TRANSFER_TX='8697ad2c4e1713227c16a65a5845636458df2d3db3adf526e07e17699bc6b3c4' TRON_TOKEN_TRANSFER_TX='bd0ba6ebb8d2f910b27de1565c66cc89337b792dfdb6484847c817ccbd240760' TRON_NFT_TRANSFER_TX='d5dd97c09efdb93f36808a9f8e14642ef226880aa91a846583d4ce98c0084637' -#TRON +#Tron #Bitcoin BTC_TRANSFER_TEST_IS_ACTIVE=false @@ -92,4 +92,43 @@ BTC_SENDER_PRIVATE_KEY='cNHUtnWqwAwGajUGjyHLNbUcfHaDC3ujqjc6qcZik5Xa58Hj46vG' BTC_SENDER_ADDRESS='tb1q8juz7c302wdcpfz83zvvyf4jxc8sfq4wyth3pr' BTC_RECEIVER_ADDRESS='tb1q9uxj8p043sjkm0qzlsys7677mv98j76k8cvgtg' BTC_TRANSFER_AMOUNT=0.00001 -#Bitcoin \ No newline at end of file +#Bitcoin + +#Solana +# Assets +SOL_COIN_TRANSFER_TEST_IS_ACTIVE=false +SOL_TOKEN_TRANSFER_TEST_IS_ACTIVE=false +SOL_TOKEN_APPROVE_TEST_IS_ACTIVE=false +SOL_TOKEN_TRANSFER_FROM_TEST_IS_ACTIVE=false +SOL_NFT_TRANSACTION_TEST_IS_ACTIVE=false +SOL_TRANSACTION_LISTENER_TEST_IS_ACTIVE=false + +SOL_COIN_BALANCE_TEST_AMOUNT=1 +SOL_TOKEN_BALANCE_TEST_AMOUNT=20 +SOL_NFT_BALANCE_TEST_AMOUNT=2 +SOL_TRANSFER_TEST_AMOUNT=0.001 +SOL_TOKEN_TRANSFER_TEST_AMOUNT=1 +SOL_TOKEN_APPROVE_TEST_AMOUNT=10 +SOL_NFT_TRANSFER_ID='...' + +SOL_BALANCE_TEST_ADDRESS='2i6NifwwBGJKUEhYhqbGwu66kDhbfyjgp7zPN5dQsKsE' +SOL_SENDER_PRIVATE_KEY='2hh51RHd1cEgiuEj2azZJFNphh27S8578otEHw8WvUia1yEBaW7o7XNuxdV1qQYbvxL5FHrcHpbZMCCxULTkCHRq' +SOL_RECEIVER_PRIVATE_KEY='57XnG9wtVMVV5BZnZbmaN3JTQ7Mzkmbyh4ooMC45YypJz3gF16nGfCJw3hWGQjLFbKmruaF3N3BH3fJAGD6stGCb' +SOL_SENDER_TEST_ADDRESS='7bn9So6CKmdn2vHYZU5oG6gaVEewW3N7U8vJoNmSv2vB' +SOL_RECEIVER_TEST_ADDRESS='GHVMV3zZscR8V4K5GEgQTUjuV4jEixB9a4QX3KhgvVKy' +SOL_TOKEN_TEST_ADDRESS='2ZHwL3dXk3szRgiBLZi244NmKs2VmoBx764AYMY2tQfx' +SOL_NFT_TEST_ADDRESS='...' +# Assets + +# Models +SOL_NFT_ID=8 +SOL_TOKEN_AMOUNT=20 +SOL_COIN_AMOUNT=10 + +SOL_MODEL_TEST_SENDER='37p742pby4ACHiGcT3d58gsjmC3Kd9bH2L89E3hY8FHZ' +SOL_MODEL_TEST_RECEIVER='7bn9So6CKmdn2vHYZU5oG6gaVEewW3N7U8vJoNmSv2vB' + +SOL_TRANSFER_TX='2RDU1otuPR6UtevwYCQWnngvvjPiTFuHFdyCnzwQVR8wyZ7niqACt2QBmfuyD5aXJbEXSEUcqFquiCEtcQZzkWif' +SOL_TOKEN_TRANSFER_TX='4XLpHmpiKXXDM7pAg8CXeSLjw7SYKZaSzJjXHP2E1vL2ndvrJ6GnuHUvaQpY3LHQeJww8fzFLJ9MiLnvgsyyyt3i' +SOL_NFT_TRANSFER_TX='...' +#Solana \ No newline at end of file From df37f56f55dd14f404aea5c9a92e5c2d7b902299 Mon Sep 17 00:00:00 2001 From: Halil Beycan <50718965+BeycanDeveloper@users.noreply.github.com> Date: Fri, 17 May 2024 16:04:38 +0800 Subject: [PATCH 30/90] created nft for test process --- .env.example | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.env.example b/.env.example index c8ad657..4344f7f 100644 --- a/.env.example +++ b/.env.example @@ -109,7 +109,7 @@ SOL_NFT_BALANCE_TEST_AMOUNT=2 SOL_TRANSFER_TEST_AMOUNT=0.001 SOL_TOKEN_TRANSFER_TEST_AMOUNT=1 SOL_TOKEN_APPROVE_TEST_AMOUNT=10 -SOL_NFT_TRANSFER_ID='...' +SOL_NFT_TRANSFER_ID='FxN19KB5UeZJFwxLFgT57WvYYXYhBFKxVumfq37xU4Ck' #NFT ID SOL_BALANCE_TEST_ADDRESS='2i6NifwwBGJKUEhYhqbGwu66kDhbfyjgp7zPN5dQsKsE' SOL_SENDER_PRIVATE_KEY='2hh51RHd1cEgiuEj2azZJFNphh27S8578otEHw8WvUia1yEBaW7o7XNuxdV1qQYbvxL5FHrcHpbZMCCxULTkCHRq' @@ -117,12 +117,12 @@ SOL_RECEIVER_PRIVATE_KEY='57XnG9wtVMVV5BZnZbmaN3JTQ7Mzkmbyh4ooMC45YypJz3gF16nGfC SOL_SENDER_TEST_ADDRESS='7bn9So6CKmdn2vHYZU5oG6gaVEewW3N7U8vJoNmSv2vB' SOL_RECEIVER_TEST_ADDRESS='GHVMV3zZscR8V4K5GEgQTUjuV4jEixB9a4QX3KhgvVKy' SOL_TOKEN_TEST_ADDRESS='2ZHwL3dXk3szRgiBLZi244NmKs2VmoBx764AYMY2tQfx' -SOL_NFT_TEST_ADDRESS='...' +SOL_NFT_TEST_ADDRESS='9B8bxQWovwm5na85xtDPuAyUVingcVdqWk3d9yQV2zsA' #Collection Mint Address # Assets # Models -SOL_NFT_ID=8 -SOL_TOKEN_AMOUNT=20 +SOL_NFT_ID='BFqd1SZFWMci42bUrhxzWhnvodCnG32xKYZkSp2rXVAf' +SOL_TOKEN_AMOUNT=50000 SOL_COIN_AMOUNT=10 SOL_MODEL_TEST_SENDER='37p742pby4ACHiGcT3d58gsjmC3Kd9bH2L89E3hY8FHZ' @@ -130,5 +130,5 @@ SOL_MODEL_TEST_RECEIVER='7bn9So6CKmdn2vHYZU5oG6gaVEewW3N7U8vJoNmSv2vB' SOL_TRANSFER_TX='2RDU1otuPR6UtevwYCQWnngvvjPiTFuHFdyCnzwQVR8wyZ7niqACt2QBmfuyD5aXJbEXSEUcqFquiCEtcQZzkWif' SOL_TOKEN_TRANSFER_TX='4XLpHmpiKXXDM7pAg8CXeSLjw7SYKZaSzJjXHP2E1vL2ndvrJ6GnuHUvaQpY3LHQeJww8fzFLJ9MiLnvgsyyyt3i' -SOL_NFT_TRANSFER_TX='...' +SOL_NFT_TRANSFER_TX='3vrCoNVmeNgGG4LB1qvvdx21TYm6dnPBmhFqXChsusuLn5ZEjFZNFG3BwQQ8fodBYiPXG8QokdBLWjRtxgi7tnRD' #Solana \ No newline at end of file From f25e749d1ea803199584257c9ae70a94989d4bfe Mon Sep 17 00:00:00 2001 From: Halil Beycan <50718965+BeycanDeveloper@users.noreply.github.com> Date: Fri, 17 May 2024 18:09:42 +0800 Subject: [PATCH 31/90] added token program 2022 data --- .env.example | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.env.example b/.env.example index 4344f7f..a47fcb7 100644 --- a/.env.example +++ b/.env.example @@ -117,6 +117,7 @@ SOL_RECEIVER_PRIVATE_KEY='57XnG9wtVMVV5BZnZbmaN3JTQ7Mzkmbyh4ooMC45YypJz3gF16nGfC SOL_SENDER_TEST_ADDRESS='7bn9So6CKmdn2vHYZU5oG6gaVEewW3N7U8vJoNmSv2vB' SOL_RECEIVER_TEST_ADDRESS='GHVMV3zZscR8V4K5GEgQTUjuV4jEixB9a4QX3KhgvVKy' SOL_TOKEN_TEST_ADDRESS='2ZHwL3dXk3szRgiBLZi244NmKs2VmoBx764AYMY2tQfx' +SOL_TOKEN_2022_TEST_ADDRESS='FQPbc46pp1b3QWHFJFfsvQrv7YedX8XEum5c18mLnipE' SOL_NFT_TEST_ADDRESS='9B8bxQWovwm5na85xtDPuAyUVingcVdqWk3d9yQV2zsA' #Collection Mint Address # Assets @@ -130,5 +131,6 @@ SOL_MODEL_TEST_RECEIVER='7bn9So6CKmdn2vHYZU5oG6gaVEewW3N7U8vJoNmSv2vB' SOL_TRANSFER_TX='2RDU1otuPR6UtevwYCQWnngvvjPiTFuHFdyCnzwQVR8wyZ7niqACt2QBmfuyD5aXJbEXSEUcqFquiCEtcQZzkWif' SOL_TOKEN_TRANSFER_TX='4XLpHmpiKXXDM7pAg8CXeSLjw7SYKZaSzJjXHP2E1vL2ndvrJ6GnuHUvaQpY3LHQeJww8fzFLJ9MiLnvgsyyyt3i' +SOL_TOKEN_2022_TRANSFER_TX='3c2Myd3k4Pw1NbsCjuskkZCtbD9HRTjoyoxh2u7qsVLgFN1RbRYAXXRKzBRzwTAmv2pXDjArbotzVL6AVehBMeyg' SOL_NFT_TRANSFER_TX='3vrCoNVmeNgGG4LB1qvvdx21TYm6dnPBmhFqXChsusuLn5ZEjFZNFG3BwQQ8fodBYiPXG8QokdBLWjRtxgi7tnRD' #Solana \ No newline at end of file From bd96e708eeee1481bf0919e6d53fa0402f76e7c2 Mon Sep 17 00:00:00 2001 From: Halil Beycan <50718965+BeycanDeveloper@users.noreply.github.com> Date: Fri, 17 May 2024 18:30:56 +0800 Subject: [PATCH 32/90] Added standby option --- .../networks/bitcoin/src/models/Transaction.ts | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/packages/networks/bitcoin/src/models/Transaction.ts b/packages/networks/bitcoin/src/models/Transaction.ts index 00b19c0..7d284de 100644 --- a/packages/networks/bitcoin/src/models/Transaction.ts +++ b/packages/networks/bitcoin/src/models/Transaction.ts @@ -1,5 +1,5 @@ -import axios from 'axios' -import { fromSatoshi } from '../utils.ts' +import { fromSatoshi, sleep } from '../utils.ts' +import axios, { type AxiosError } from 'axios' import { Provider } from '../services/Provider.ts' import type { TransactionInterface } from '@multiplechain/types' import { ErrorTypeEnum, TransactionStatusEnum } from '@multiplechain/types' @@ -46,6 +46,8 @@ export interface TransactionData { } } +let counter = 0 + export class Transaction implements TransactionInterface { /** * Each transaction has its own unique ID defined by the user @@ -87,6 +89,16 @@ export class Transaction implements TransactionInterface { return (this.data = data as TransactionData) } catch (error) { + const axiosError = error as AxiosError + // Returns empty data when the transaction is first created. For this reason, it would be better to check it intermittently and give an error if it still does not exist. Average 10 seconds. + if (String(axiosError?.response?.data).includes('Transaction not found')) { + if (counter > 5) { + throw new Error('Transaction not found') + } + counter++ + await sleep(2000) + return await this.getData() + } throw new Error(ErrorTypeEnum.RPC_REQUEST_ERROR) } } From 520547ec5f75e967f64e69681fa29011bee9f0f5 Mon Sep 17 00:00:00 2001 From: Halil Beycan <50718965+BeycanDeveloper@users.noreply.github.com> Date: Fri, 17 May 2024 18:33:43 +0800 Subject: [PATCH 33/90] returned if is it null --- packages/networks/bitcoin/src/models/Transaction.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/networks/bitcoin/src/models/Transaction.ts b/packages/networks/bitcoin/src/models/Transaction.ts index 7d284de..f99ffb8 100644 --- a/packages/networks/bitcoin/src/models/Transaction.ts +++ b/packages/networks/bitcoin/src/models/Transaction.ts @@ -74,7 +74,7 @@ export class Transaction implements TransactionInterface { } /** - * @returns {Promise} Transaction data + * @returns {Promise} Transaction data */ async getData(): Promise { if (this.data !== null) { @@ -84,7 +84,7 @@ export class Transaction implements TransactionInterface { const data = (await axios.get(this.provider.createEndpoint('tx/' + this.id))).data if (data?.txid !== this.id) { - this.data = null + return (this.data = null) } return (this.data = data as TransactionData) From a944c1bdc971e44277cadc5ee430f4119f4768b8 Mon Sep 17 00:00:00 2001 From: Halil Beycan <50718965+BeycanDeveloper@users.noreply.github.com> Date: Fri, 17 May 2024 19:18:32 +0800 Subject: [PATCH 34/90] transaction model completed --- .../networks/solana/src/models/Transaction.ts | 89 ++++++++++++++++--- .../networks/solana/src/services/Provider.ts | 8 +- packages/networks/solana/tests/models.spec.ts | 62 ++++++++++++- 3 files changed, 139 insertions(+), 20 deletions(-) diff --git a/packages/networks/solana/src/models/Transaction.ts b/packages/networks/solana/src/models/Transaction.ts index 15f111d..642d37e 100644 --- a/packages/networks/solana/src/models/Transaction.ts +++ b/packages/networks/solana/src/models/Transaction.ts @@ -1,6 +1,8 @@ +import { math } from '@multiplechain/utils' import { Provider } from '../services/Provider.ts' import type { TransactionInterface } from '@multiplechain/types' -import { TransactionStatusEnum } from '@multiplechain/types' +import type { ParsedTransactionWithMeta } from '@solana/web3.js' +import { ErrorTypeEnum, TransactionStatusEnum } from '@multiplechain/types' export class Transaction implements TransactionInterface { /** @@ -13,6 +15,8 @@ export class Transaction implements TransactionInterface { */ provider: Provider + data: ParsedTransactionWithMeta | null = null + /** * @param {string} id Transaction id * @param {Provider} provider Blockchain network provider @@ -25,15 +29,57 @@ export class Transaction implements TransactionInterface { /** * @returns {Promise} Transaction data */ - async getData(): Promise { - return {} + async getData(): Promise { + if (this.data !== null) { + return this.data + } + try { + const data = await this.provider.web3.getParsedTransaction(this.id, { + commitment: 'confirmed' + }) + + if (data === null) { + return null + } + + return (this.data = data) + } catch (error) { + throw new Error(ErrorTypeEnum.RPC_REQUEST_ERROR) + } } /** - * @returns {Promise} Wait for the transaction to be confirmed + * @param {number} ms - Milliseconds to wait for the transaction to be confirmed. Default is 4000ms + * @returns {Promise} Status of the transaction */ - async wait(): Promise { - return await Promise.resolve(TransactionStatusEnum.CONFIRMED) + async wait(ms: number = 4000): Promise { + return await new Promise((resolve, reject) => { + const check = async (): Promise => { + try { + let status = await this.getStatus() + if (status === TransactionStatusEnum.PENDING) { + const latestBlockHash = await this.provider.web3.getLatestBlockhash() + await this.provider.web3.confirmTransaction({ + signature: this.id, + blockhash: latestBlockHash.blockhash, + lastValidBlockHeight: latestBlockHash.lastValidBlockHeight + }) + status = await this.getStatus() + } + if (status === TransactionStatusEnum.CONFIRMED) { + resolve(TransactionStatusEnum.CONFIRMED) + return + } else if (status === TransactionStatusEnum.FAILED) { + reject(TransactionStatusEnum.FAILED) + return + } + setTimeout(check, ms) + } catch (error) { + reject(TransactionStatusEnum.FAILED) + } + } + void check() + }) } /** @@ -47,48 +93,65 @@ export class Transaction implements TransactionInterface { * @returns {string} Transaction URL */ getUrl(): string { - return 'example' + const node = this.provider.node + let transactionUrl = this.provider.node.explorerUrl + 'tx/' + this.id + transactionUrl += node.cluster !== 'mainnet-beta' ? '?cluster=' + node.cluster : '' + return transactionUrl } /** * @returns {Promise} Wallet address of the sender of transaction */ async getSigner(): Promise { - return 'example' + const data = await this.getData() + return data?.transaction?.message?.accountKeys[0].pubkey.toBase58() ?? '' } /** * @returns {Promise} Transaction fee */ async getFee(): Promise { - return 0 + const data = await this.getData() + return math.div(data?.meta?.fee ?? 0, 10 ** 9) } /** * @returns {Promise} Block number that transaction */ async getBlockNumber(): Promise { - return 0 + const data = await this.getData() + return data?.slot ?? 0 } /** * @returns {Promise} Block timestamp that transaction */ async getBlockTimestamp(): Promise { - return 0 + const data = await this.getData() + return data?.blockTime ?? 0 } /** * @returns {Promise} Confirmation count of the block */ async getBlockConfirmationCount(): Promise { - return 0 + const data = await this.getData() + const currentSlot = await this.provider.web3.getSlot() + return currentSlot - (data?.slot ?? 0) } /** * @returns {Promise} Status of the transaction */ async getStatus(): Promise { - return TransactionStatusEnum.CONFIRMED + const data = await this.getData() + + if (data === null) { + return TransactionStatusEnum.PENDING + } + + return data.meta?.err !== null + ? TransactionStatusEnum.FAILED + : TransactionStatusEnum.CONFIRMED } } diff --git a/packages/networks/solana/src/services/Provider.ts b/packages/networks/solana/src/services/Provider.ts index d5645b7..190cc47 100644 --- a/packages/networks/solana/src/services/Provider.ts +++ b/packages/networks/solana/src/services/Provider.ts @@ -8,8 +8,8 @@ import { Connection } from '@solana/web3.js' import { checkWebSocket } from '@multiplechain/utils' export interface SolanaNodeInfoInterface { - node: string name: string + cluster: string wsUrl?: string rpcUrl: string explorerUrl: string @@ -28,15 +28,15 @@ export class Provider implements ProviderInterface { */ nodes: SolanaNodeInfoListInterface = { mainnet: { - node: 'mainnet-beta', name: 'Mainnet', + cluster: 'mainnet-beta', rpcUrl: 'https://api.mainnet-beta.solana.com/', explorerUrl: 'https://solscan.io/' }, devnet: { - node: 'devnet', name: 'Devnet', - rpcUrl: 'https://api.devnet.solana.com', + cluster: 'devnet', + rpcUrl: 'https://api.devnet.solana.com/', explorerUrl: 'https://solscan.io/' } } diff --git a/packages/networks/solana/tests/models.spec.ts b/packages/networks/solana/tests/models.spec.ts index 34c5579..1dbe2a8 100644 --- a/packages/networks/solana/tests/models.spec.ts +++ b/packages/networks/solana/tests/models.spec.ts @@ -1,7 +1,63 @@ import { describe, it, expect } from 'vitest' -describe('example', () => { - it('should work', () => { - expect(1 + 1).toBe(2) +import { Transaction } from '../src/models/Transaction.ts' +import { NftTransaction } from '../src/models/NftTransaction.ts' +import { CoinTransaction } from '../src/models/CoinTransaction.ts' +import { TokenTransaction } from '../src/models/TokenTransaction.ts' +import { AssetDirectionEnum, TransactionStatusEnum } from '@multiplechain/types' + +const nftId = String(process.env.SOL_NFT_ID) +const tokenAmount = Number(process.env.SOL_TOKEN_AMOUNT) +const coinAmount = Number(process.env.SOL_COIN_AMOUNT) + +const solTransferTx = String(process.env.SOL_TRANSFER_TX) +const tokenTransferTx = String(process.env.SOL_TOKEN_TRANSFER_TX) +const nftTransferTx = String(process.env.SOL_NFT_TRANSFER_TX) + +const sender = String(process.env.SOL_MODEL_TEST_SENDER) +const receiver = String(process.env.SOL_MODEL_TEST_RECEIVER) + +describe('Transaction', () => { + const tx = new Transaction(solTransferTx) + it('Id', async () => { + expect(tx.getId()).toBe(solTransferTx) + }) + + it('Data', async () => { + expect(await tx.getData()).toBeTypeOf('object') + }) + + it('Wait', async () => { + expect(await tx.wait()).toBe(TransactionStatusEnum.CONFIRMED) + }) + + it('URL', async () => { + expect(tx.getUrl()).toBe( + 'https://solscan.io/tx/2RDU1otuPR6UtevwYCQWnngvvjPiTFuHFdyCnzwQVR8wyZ7niqACt2QBmfuyD5aXJbEXSEUcqFquiCEtcQZzkWif?cluster=devnet' + ) + }) + + it('Sender', async () => { + expect(await tx.getSigner()).toBe(sender) + }) + + it('Fee', async () => { + expect(await tx.getFee()).toBe(0.000065) + }) + + it('Block Number', async () => { + expect(await tx.getBlockNumber()).toBe(299257452) + }) + + it('Block Timestamp', async () => { + expect(await tx.getBlockTimestamp()).toBe(1715865360) + }) + + it('Block Confirmation Count', async () => { + expect(await tx.getBlockConfirmationCount()).toBeGreaterThan(4567) + }) + + it('Status', async () => { + expect(await tx.getStatus()).toBe(TransactionStatusEnum.CONFIRMED) }) }) From 2bef18e66fa9641bd2fc9deb2956eb83c095fa54 Mon Sep 17 00:00:00 2001 From: Halil Beycan <50718965+BeycanDeveloper@users.noreply.github.com> Date: Fri, 17 May 2024 19:44:27 +0800 Subject: [PATCH 35/90] coin model completed --- .../solana/src/models/CoinTransaction.ts | 53 +++++++++++++++++-- packages/networks/solana/tests/models.spec.ts | 26 +++++++++ 2 files changed, 74 insertions(+), 5 deletions(-) diff --git a/packages/networks/solana/src/models/CoinTransaction.ts b/packages/networks/solana/src/models/CoinTransaction.ts index 9857f2e..920ebe5 100644 --- a/packages/networks/solana/src/models/CoinTransaction.ts +++ b/packages/networks/solana/src/models/CoinTransaction.ts @@ -1,27 +1,50 @@ +import { math } from '@multiplechain/utils' import { Transaction } from './Transaction.ts' +import type { ParsedInstruction } from '@solana/web3.js' import { TransactionStatusEnum } from '@multiplechain/types' -import type { AssetDirectionEnum, CoinTransactionInterface } from '@multiplechain/types' +import { AssetDirectionEnum, type CoinTransactionInterface } from '@multiplechain/types' export class CoinTransaction extends Transaction implements CoinTransactionInterface { /** * @returns {Promise} Wallet address of the receiver of transaction */ async getReceiver(): Promise { - return 'example' + const data = await this.getData() + if (data === null) { + return '' + } + + const instruction = data.transaction.message.instructions[2] as ParsedInstruction + + return instruction.parsed.info.destination } /** * @returns {Promise} Wallet address of the sender of transaction */ async getSender(): Promise { - return 'example' + const data = await this.getData() + if (data === null) { + return '' + } + + const instruction = data.transaction.message.instructions[2] as ParsedInstruction + + return instruction.parsed.info.source } /** * @returns {Promise} Amount of coin that will be transferred */ async getAmount(): Promise { - return 0 + const data = await this.getData() + if (data === null) { + return 0 + } + + const instruction = data.transaction.message.instructions[2] as ParsedInstruction + + return math.div(instruction.parsed.info.lamports as number, 10 ** 9) } /** @@ -35,6 +58,26 @@ export class CoinTransaction extends Transaction implements CoinTransactionInter address: string, amount: number ): Promise { - return TransactionStatusEnum.PENDING + const status = await this.getStatus() + + if (status === TransactionStatusEnum.PENDING) { + return TransactionStatusEnum.PENDING + } + + if ((await this.getAmount()) !== amount) { + return TransactionStatusEnum.FAILED + } + + if (direction === AssetDirectionEnum.INCOMING) { + if ((await this.getReceiver()).toLowerCase() !== address.toLowerCase()) { + return TransactionStatusEnum.FAILED + } + } else { + if ((await this.getSender()).toLowerCase() !== address.toLowerCase()) { + return TransactionStatusEnum.FAILED + } + } + + return TransactionStatusEnum.CONFIRMED } } diff --git a/packages/networks/solana/tests/models.spec.ts b/packages/networks/solana/tests/models.spec.ts index 1dbe2a8..84a4fcc 100644 --- a/packages/networks/solana/tests/models.spec.ts +++ b/packages/networks/solana/tests/models.spec.ts @@ -61,3 +61,29 @@ describe('Transaction', () => { expect(await tx.getStatus()).toBe(TransactionStatusEnum.CONFIRMED) }) }) + +describe('Coin Transaction', () => { + const tx = new CoinTransaction(solTransferTx) + + it('Receiver', async () => { + expect((await tx.getReceiver()).toLowerCase()).toBe(receiver.toLowerCase()) + }) + + it('Amount', async () => { + expect(await tx.getAmount()).toBe(coinAmount) + }) + + it('Verify Transfer', async () => { + expect(await tx.verifyTransfer(AssetDirectionEnum.INCOMING, receiver, coinAmount)).toBe( + TransactionStatusEnum.CONFIRMED + ) + + expect(await tx.verifyTransfer(AssetDirectionEnum.OUTGOING, sender, coinAmount)).toBe( + TransactionStatusEnum.CONFIRMED + ) + + expect(await tx.verifyTransfer(AssetDirectionEnum.OUTGOING, receiver, coinAmount)).toBe( + TransactionStatusEnum.FAILED + ) + }) +}) From aa7de56359008eda7fccbc948aa11492dac53e67 Mon Sep 17 00:00:00 2001 From: Halil Beycan <50718965+BeycanDeveloper@users.noreply.github.com> Date: Fri, 17 May 2024 19:51:00 +0800 Subject: [PATCH 36/90] stabilized --- .../solana/src/models/CoinTransaction.ts | 21 +++++++++++-------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/packages/networks/solana/src/models/CoinTransaction.ts b/packages/networks/solana/src/models/CoinTransaction.ts index 920ebe5..96ae017 100644 --- a/packages/networks/solana/src/models/CoinTransaction.ts +++ b/packages/networks/solana/src/models/CoinTransaction.ts @@ -5,6 +5,15 @@ import { TransactionStatusEnum } from '@multiplechain/types' import { AssetDirectionEnum, type CoinTransactionInterface } from '@multiplechain/types' export class CoinTransaction extends Transaction implements CoinTransactionInterface { + /** + * @returns {Promise} Wallet address of the receiver of transaction + */ + findTransferInstruction(data: any): ParsedInstruction { + return data.transaction.message.instructions.find((instruction: any): boolean => { + return instruction.parsed !== undefined && instruction.parsed.type === 'transfer' + }) as ParsedInstruction + } + /** * @returns {Promise} Wallet address of the receiver of transaction */ @@ -14,9 +23,7 @@ export class CoinTransaction extends Transaction implements CoinTransactionInter return '' } - const instruction = data.transaction.message.instructions[2] as ParsedInstruction - - return instruction.parsed.info.destination + return this.findTransferInstruction(data).parsed.info.destination } /** @@ -28,9 +35,7 @@ export class CoinTransaction extends Transaction implements CoinTransactionInter return '' } - const instruction = data.transaction.message.instructions[2] as ParsedInstruction - - return instruction.parsed.info.source + return this.findTransferInstruction(data).parsed.info.source } /** @@ -42,9 +47,7 @@ export class CoinTransaction extends Transaction implements CoinTransactionInter return 0 } - const instruction = data.transaction.message.instructions[2] as ParsedInstruction - - return math.div(instruction.parsed.info.lamports as number, 10 ** 9) + return math.div(this.findTransferInstruction(data).parsed.info.lamports as number, 10 ** 9) } /** From 2a5b5b9549a9fdf68eb4629d013bf76d1a5e9ee8 Mon Sep 17 00:00:00 2001 From: Halil Beycan <50718965+BeycanDeveloper@users.noreply.github.com> Date: Fri, 17 May 2024 20:09:04 +0800 Subject: [PATCH 37/90] completed token model --- .../solana/src/models/TokenTransaction.ts | 69 +++++++++++++++++-- packages/networks/solana/tests/models.spec.ts | 58 ++++++++++++++++ 2 files changed, 121 insertions(+), 6 deletions(-) diff --git a/packages/networks/solana/src/models/TokenTransaction.ts b/packages/networks/solana/src/models/TokenTransaction.ts index b1ea29e..18142cf 100644 --- a/packages/networks/solana/src/models/TokenTransaction.ts +++ b/packages/networks/solana/src/models/TokenTransaction.ts @@ -1,27 +1,64 @@ -import { ContractTransaction } from './ContractTransaction.ts' +import type { ParsedInstruction } from '@solana/web3.js' import { TransactionStatusEnum } from '@multiplechain/types' -import type { AssetDirectionEnum, TokenTransactionInterface } from '@multiplechain/types' +import { ContractTransaction } from './ContractTransaction.ts' +import { AssetDirectionEnum, type TokenTransactionInterface } from '@multiplechain/types' export class TokenTransaction extends ContractTransaction implements TokenTransactionInterface { + /** + * @returns {Promise} Wallet address of the receiver of transaction + */ + findTransferInstruction(data: any): ParsedInstruction { + return data.transaction.message.instructions.find((instruction: any): boolean => { + return ( + instruction.parsed !== undefined && + (instruction.parsed.type === 'transferChecked' || + instruction.parsed.type === 'transfer') + ) + }) as ParsedInstruction + } + /** * @returns {Promise} Wallet address of the receiver of transaction */ async getReceiver(): Promise { - return 'example' + const data = await this.getData() + if (data === null) { + return '' + } + + if (data.meta?.postTokenBalances?.length === undefined) { + return '' + } + + return data.meta.postTokenBalances[1].owner ?? '' } /** * @returns {Promise} Wallet address of the sender of transaction */ async getSender(): Promise { - return 'example' + const data = await this.getData() + if (data === null) { + return '' + } + + if (data.meta?.postTokenBalances?.length === undefined) { + return '' + } + + return data.meta.postTokenBalances[0].owner ?? '' } /** * @returns {Promise} Amount of tokens that will be transferred */ async getAmount(): Promise { - return 0 + const data = await this.getData() + if (data === null) { + return 0 + } + + return this.findTransferInstruction(data).parsed.info.tokenAmount.uiAmount as number } /** @@ -35,6 +72,26 @@ export class TokenTransaction extends ContractTransaction implements TokenTransa address: string, amount: number ): Promise { - return TransactionStatusEnum.PENDING + const status = await this.getStatus() + + if (status === TransactionStatusEnum.PENDING) { + return TransactionStatusEnum.PENDING + } + + if ((await this.getAmount()) !== amount) { + return TransactionStatusEnum.FAILED + } + + if (direction === AssetDirectionEnum.INCOMING) { + if ((await this.getReceiver()).toLowerCase() !== address.toLowerCase()) { + return TransactionStatusEnum.FAILED + } + } else { + if ((await this.getSender()).toLowerCase() !== address.toLowerCase()) { + return TransactionStatusEnum.FAILED + } + } + + return TransactionStatusEnum.CONFIRMED } } diff --git a/packages/networks/solana/tests/models.spec.ts b/packages/networks/solana/tests/models.spec.ts index 84a4fcc..f1882c2 100644 --- a/packages/networks/solana/tests/models.spec.ts +++ b/packages/networks/solana/tests/models.spec.ts @@ -12,6 +12,7 @@ const coinAmount = Number(process.env.SOL_COIN_AMOUNT) const solTransferTx = String(process.env.SOL_TRANSFER_TX) const tokenTransferTx = String(process.env.SOL_TOKEN_TRANSFER_TX) +const token2022TransferTx = String(process.env.SOL_TOKEN_2022_TRANSFER_TX) const nftTransferTx = String(process.env.SOL_NFT_TRANSFER_TX) const sender = String(process.env.SOL_MODEL_TEST_SENDER) @@ -87,3 +88,60 @@ describe('Coin Transaction', () => { ) }) }) + +describe('Token Transaction', () => { + const tx = new TokenTransaction(tokenTransferTx) + const tx2022 = new TokenTransaction(token2022TransferTx) + + it('Receiver', async () => { + expect((await tx.getReceiver()).toLowerCase()).toBe(receiver.toLowerCase()) + }) + + it('Sender', async () => { + expect((await tx.getSender()).toLowerCase()).toBe(sender.toLowerCase()) + }) + + it('Amount', async () => { + expect(await tx.getAmount()).toBe(tokenAmount) + }) + + it('Verify Transfer', async () => { + expect(await tx.verifyTransfer(AssetDirectionEnum.INCOMING, receiver, tokenAmount)).toBe( + TransactionStatusEnum.CONFIRMED + ) + + expect(await tx.verifyTransfer(AssetDirectionEnum.OUTGOING, sender, tokenAmount)).toBe( + TransactionStatusEnum.CONFIRMED + ) + + expect(await tx.verifyTransfer(AssetDirectionEnum.OUTGOING, receiver, tokenAmount)).toBe( + TransactionStatusEnum.FAILED + ) + }) + + it('Receiver', async () => { + expect((await tx2022.getReceiver()).toLowerCase()).toBe(receiver.toLowerCase()) + }) + + it('Sender', async () => { + expect((await tx2022.getSender()).toLowerCase()).toBe(sender.toLowerCase()) + }) + + it('Amount', async () => { + expect(await tx2022.getAmount()).toBe(tokenAmount) + }) + + it('Verify Transfer', async () => { + expect( + await tx2022.verifyTransfer(AssetDirectionEnum.INCOMING, receiver, tokenAmount) + ).toBe(TransactionStatusEnum.CONFIRMED) + + expect(await tx2022.verifyTransfer(AssetDirectionEnum.OUTGOING, sender, tokenAmount)).toBe( + TransactionStatusEnum.CONFIRMED + ) + + expect(await tx.verifyTransfer(AssetDirectionEnum.OUTGOING, receiver, tokenAmount)).toBe( + TransactionStatusEnum.FAILED + ) + }) +}) From 3a955bf17555e5a7b2f542428da2d810337912ff Mon Sep 17 00:00:00 2001 From: Halil Beycan <50718965+BeycanDeveloper@users.noreply.github.com> Date: Fri, 17 May 2024 20:21:29 +0800 Subject: [PATCH 38/90] nft model completed --- .../solana/src/models/NftTransaction.ts | 75 ++++++++++++++++--- packages/networks/solana/tests/models.spec.ts | 34 +++++++++ 2 files changed, 99 insertions(+), 10 deletions(-) diff --git a/packages/networks/solana/src/models/NftTransaction.ts b/packages/networks/solana/src/models/NftTransaction.ts index 09b8d80..6183602 100644 --- a/packages/networks/solana/src/models/NftTransaction.ts +++ b/packages/networks/solana/src/models/NftTransaction.ts @@ -1,41 +1,96 @@ -import { ContractTransaction } from './ContractTransaction.ts' +import type { ParsedInstruction } from '@solana/web3.js' import { TransactionStatusEnum } from '@multiplechain/types' -import type { NftTransactionInterface, AssetDirectionEnum } from '@multiplechain/types' +import { ContractTransaction } from './ContractTransaction.ts' +import { type NftTransactionInterface, AssetDirectionEnum } from '@multiplechain/types' export class NftTransaction extends ContractTransaction implements NftTransactionInterface { + /** + * @returns {Promise} Wallet address of the receiver of transaction + */ + findTransferInstruction(data: any): ParsedInstruction { + return data.transaction.message.instructions.find((instruction: any): boolean => { + return ( + instruction.parsed !== undefined && + (instruction.parsed.type === 'transferChecked' || + instruction.parsed.type === 'transfer') + ) + }) as ParsedInstruction + } + /** * @returns {Promise} Receiver wallet address */ async getReceiver(): Promise { - return 'example' + const data = await this.getData() + if (data === null) { + return '' + } + + if (data.meta?.postTokenBalances?.length === undefined) { + return '' + } + + return data.meta.postTokenBalances[0].owner ?? '' } /** * @returns {Promise} Wallet address of the sender of transaction */ async getSender(): Promise { - return 'example' + const data = await this.getData() + + if (data === null) { + return '' + } + + return this.findTransferInstruction(data).parsed.info.authority } /** - * @returns {Promise} NFT ID + * @returns {Promise} NFT ID */ - async getNftId(): Promise { - return 0 + async getNftId(): Promise { + const data = await this.getData() + + if (data === null) { + return '' + } + + return this.findTransferInstruction(data).parsed.info.mint } /** * @param {AssetDirectionEnum} direction - Direction of the transaction (nft) * @param {string} address - Wallet address of the receiver or sender of the transaction, dependant on direction - * @param {number} nftId ID of the NFT that will be transferred + * @param {string} nftId ID of the NFT that will be transferred * @override verifyTransfer() in AssetTransactionInterface * @returns {Promise} Status of the transaction */ async verifyTransfer( direction: AssetDirectionEnum, address: string, - nftId: number | string + nftId: string | number ): Promise { - return TransactionStatusEnum.PENDING + const status = await this.getStatus() + + if (status === TransactionStatusEnum.PENDING) { + return TransactionStatusEnum.PENDING + } + + if ((await this.getNftId()) !== nftId) { + return TransactionStatusEnum.FAILED + } + + if (direction === AssetDirectionEnum.INCOMING) { + if ((await this.getReceiver()).toLowerCase() !== address.toLowerCase()) { + return TransactionStatusEnum.FAILED + } + } else { + if ((await this.getSender()).toLowerCase() !== address.toLowerCase()) { + return TransactionStatusEnum.FAILED + } + } + + return TransactionStatusEnum.CONFIRMED } } diff --git a/packages/networks/solana/tests/models.spec.ts b/packages/networks/solana/tests/models.spec.ts index f1882c2..bfa6384 100644 --- a/packages/networks/solana/tests/models.spec.ts +++ b/packages/networks/solana/tests/models.spec.ts @@ -145,3 +145,37 @@ describe('Token Transaction', () => { ) }) }) + +describe('NFT Transaction', () => { + const tx = new NftTransaction(nftTransferTx) + + it('Receiver', async () => { + expect((await tx.getReceiver()).toLowerCase()).toBe(receiver.toLowerCase()) + }) + + it('Signer', async () => { + expect((await tx.getSigner()).toLowerCase()).toBe(sender.toLowerCase()) + }) + + it('Sender', async () => { + expect((await tx.getSender()).toLowerCase()).toBe(sender.toLowerCase()) + }) + + it('NFT ID', async () => { + expect(await tx.getNftId()).toBe(nftId) + }) + + it('Verify Transfer', async () => { + expect(await tx.verifyTransfer(AssetDirectionEnum.INCOMING, receiver, nftId)).toBe( + TransactionStatusEnum.CONFIRMED + ) + + expect(await tx.verifyTransfer(AssetDirectionEnum.OUTGOING, sender, nftId)).toBe( + TransactionStatusEnum.CONFIRMED + ) + + expect(await tx.verifyTransfer(AssetDirectionEnum.OUTGOING, receiver, nftId)).toBe( + TransactionStatusEnum.FAILED + ) + }) +}) From d11388a9ccdd9d9b033f5a29e4d8a1fd48c26f93 Mon Sep 17 00:00:00 2001 From: Halil Beycan <50718965+BeycanDeveloper@users.noreply.github.com> Date: Sat, 18 May 2024 11:51:29 +0800 Subject: [PATCH 39/90] completed contract tx model --- .../solana/src/models/ContractTransaction.ts | 16 +++++++++- packages/networks/solana/tests/models.spec.ts | 31 +++++++++++++++++++ 2 files changed, 46 insertions(+), 1 deletion(-) diff --git a/packages/networks/solana/src/models/ContractTransaction.ts b/packages/networks/solana/src/models/ContractTransaction.ts index ad57241..3a11320 100644 --- a/packages/networks/solana/src/models/ContractTransaction.ts +++ b/packages/networks/solana/src/models/ContractTransaction.ts @@ -1,11 +1,25 @@ import { Transaction } from './Transaction.ts' +import type { ParsedInstruction } from '@solana/web3.js' import type { ContractTransactionInterface } from '@multiplechain/types' export class ContractTransaction extends Transaction implements ContractTransactionInterface { + /** + * @returns {Promise} Wallet address of the receiver of transaction + */ + findTransferInstruction(data: any): ParsedInstruction { + const length = data.transaction.message.instructions.length + return data.transaction.message.instructions[length - 1] as ParsedInstruction + } + /** * @returns {Promise} Contract address of the transaction */ async getAddress(): Promise { - return 'example' + const data = await this.getData() + if (data === null) { + return '' + } + + return this.findTransferInstruction(data).programId.toBase58() } } diff --git a/packages/networks/solana/tests/models.spec.ts b/packages/networks/solana/tests/models.spec.ts index bfa6384..e5ea1b6 100644 --- a/packages/networks/solana/tests/models.spec.ts +++ b/packages/networks/solana/tests/models.spec.ts @@ -5,6 +5,7 @@ import { NftTransaction } from '../src/models/NftTransaction.ts' import { CoinTransaction } from '../src/models/CoinTransaction.ts' import { TokenTransaction } from '../src/models/TokenTransaction.ts' import { AssetDirectionEnum, TransactionStatusEnum } from '@multiplechain/types' +import { ContractTransaction } from '../src/models/ContractTransaction.ts' const nftId = String(process.env.SOL_NFT_ID) const tokenAmount = Number(process.env.SOL_TOKEN_AMOUNT) @@ -89,6 +90,18 @@ describe('Coin Transaction', () => { }) }) +describe('Contract Transaction', () => { + const tx = new ContractTransaction( + '5pak57tjpTf4BfHweZryxtmJBWsJjeaU56N6CbuwuSuNyPtHwKsu6CZp6Y2L9dHqNJH33w6V895ZQLgRjANJJSR3' + ) + + it('Address', async () => { + expect((await tx.getAddress()).toLowerCase()).toBe( + 'HeXZiyduAmAaYABvrh4bU94TdzB2TkwFuNXfgi1PYFwS'.toLowerCase() + ) + }) +}) + describe('Token Transaction', () => { const tx = new TokenTransaction(tokenTransferTx) const tx2022 = new TokenTransaction(token2022TransferTx) @@ -101,6 +114,12 @@ describe('Token Transaction', () => { expect((await tx.getSender()).toLowerCase()).toBe(sender.toLowerCase()) }) + it('Program', async () => { + expect((await tx.getAddress()).toLowerCase()).toBe( + 'TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA'.toLowerCase() + ) + }) + it('Amount', async () => { expect(await tx.getAmount()).toBe(tokenAmount) }) @@ -127,6 +146,12 @@ describe('Token Transaction', () => { expect((await tx2022.getSender()).toLowerCase()).toBe(sender.toLowerCase()) }) + it('Program', async () => { + expect((await tx2022.getAddress()).toLowerCase()).toBe( + 'TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb'.toLowerCase() + ) + }) + it('Amount', async () => { expect(await tx2022.getAmount()).toBe(tokenAmount) }) @@ -157,6 +182,12 @@ describe('NFT Transaction', () => { expect((await tx.getSigner()).toLowerCase()).toBe(sender.toLowerCase()) }) + it('Program', async () => { + expect((await tx.getAddress()).toLowerCase()).toBe( + 'TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA'.toLowerCase() + ) + }) + it('Sender', async () => { expect((await tx.getSender()).toLowerCase()).toBe(sender.toLowerCase()) }) From 075f82d1ac9165396daacbf5ddad37f2a7920b4d Mon Sep 17 00:00:00 2001 From: Halil Beycan <50718965+BeycanDeveloper@users.noreply.github.com> Date: Sat, 18 May 2024 12:21:20 +0800 Subject: [PATCH 40/90] updated --- packages/networks/boilerplate/src/services/TransactionSigner.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/networks/boilerplate/src/services/TransactionSigner.ts b/packages/networks/boilerplate/src/services/TransactionSigner.ts index a76019e..c9d573a 100644 --- a/packages/networks/boilerplate/src/services/TransactionSigner.ts +++ b/packages/networks/boilerplate/src/services/TransactionSigner.ts @@ -14,7 +14,7 @@ export class TransactionSigner implements TransactionSignerInterface { /** * Signed transaction data */ - signedData?: any + signedData: any /** * Blockchain network provider From 326068a8a006925f7e9e0535ac5e63992ff0d6ee Mon Sep 17 00:00:00 2001 From: Halil Beycan <50718965+BeycanDeveloper@users.noreply.github.com> Date: Sat, 18 May 2024 12:35:29 +0800 Subject: [PATCH 41/90] coin asset completed --- packages/networks/solana/src/assets/Coin.ts | 36 +++++-- .../solana/src/models/CoinTransaction.ts | 4 +- .../networks/solana/src/models/Transaction.ts | 4 +- .../solana/src/services/TransactionSigner.ts | 56 +++++++++-- packages/networks/solana/src/utils.ts | 11 +++ packages/networks/solana/tests/assets.spec.ts | 95 ++++++++++++++++++- 6 files changed, 184 insertions(+), 22 deletions(-) create mode 100644 packages/networks/solana/src/utils.ts diff --git a/packages/networks/solana/src/assets/Coin.ts b/packages/networks/solana/src/assets/Coin.ts index 1c2d8b3..31b533e 100644 --- a/packages/networks/solana/src/assets/Coin.ts +++ b/packages/networks/solana/src/assets/Coin.ts @@ -1,5 +1,7 @@ import { Provider } from '../services/Provider.ts' -import type { CoinInterface } from '@multiplechain/types' +import { fromLamports, toLamports } from '../utils.ts' +import { PublicKey, SystemProgram, Transaction } from '@solana/web3.js' +import { ErrorTypeEnum, type CoinInterface } from '@multiplechain/types' import { CoinTransactionSigner } from '../services/TransactionSigner.ts' export class Coin implements CoinInterface { @@ -19,21 +21,21 @@ export class Coin implements CoinInterface { * @returns {string} Coin name */ getName(): string { - return 'example' + return 'Solana' } /** * @returns {string} Coin symbol */ getSymbol(): string { - return 'example' + return 'SOL' } /** * @returns {number} Decimal value of the coin */ getDecimals(): number { - return 18 + return 9 } /** @@ -41,7 +43,7 @@ export class Coin implements CoinInterface { * @returns {Promise} Wallet balance as currency of COIN */ async getBalance(owner: string): Promise { - return 0 + return fromLamports(await this.provider.web3.getBalance(new PublicKey(owner))) } /** @@ -55,6 +57,28 @@ export class Coin implements CoinInterface { receiver: string, amount: number ): Promise { - return new CoinTransactionSigner('example') + if (amount < 0) { + throw new Error(ErrorTypeEnum.INVALID_AMOUNT) + } + + if (amount > (await this.getBalance(sender))) { + throw new Error(ErrorTypeEnum.INSUFFICIENT_BALANCE) + } + + const lamports = toLamports(amount) + const senderPubKey = new PublicKey(sender) + const receiverPubKey = new PublicKey(receiver) + + const transaction = new Transaction().add( + SystemProgram.transfer({ + fromPubkey: senderPubKey, + toPubkey: receiverPubKey, + lamports + }) + ) + + transaction.feePayer = senderPubKey + + return new CoinTransactionSigner(transaction) } } diff --git a/packages/networks/solana/src/models/CoinTransaction.ts b/packages/networks/solana/src/models/CoinTransaction.ts index 96ae017..379f476 100644 --- a/packages/networks/solana/src/models/CoinTransaction.ts +++ b/packages/networks/solana/src/models/CoinTransaction.ts @@ -1,4 +1,4 @@ -import { math } from '@multiplechain/utils' +import { fromLamports } from '../utils.ts' import { Transaction } from './Transaction.ts' import type { ParsedInstruction } from '@solana/web3.js' import { TransactionStatusEnum } from '@multiplechain/types' @@ -47,7 +47,7 @@ export class CoinTransaction extends Transaction implements CoinTransactionInter return 0 } - return math.div(this.findTransferInstruction(data).parsed.info.lamports as number, 10 ** 9) + return fromLamports(this.findTransferInstruction(data).parsed.info.lamports as number) } /** diff --git a/packages/networks/solana/src/models/Transaction.ts b/packages/networks/solana/src/models/Transaction.ts index 642d37e..98f86df 100644 --- a/packages/networks/solana/src/models/Transaction.ts +++ b/packages/networks/solana/src/models/Transaction.ts @@ -1,4 +1,4 @@ -import { math } from '@multiplechain/utils' +import { fromLamports } from '../utils.ts' import { Provider } from '../services/Provider.ts' import type { TransactionInterface } from '@multiplechain/types' import type { ParsedTransactionWithMeta } from '@solana/web3.js' @@ -112,7 +112,7 @@ export class Transaction implements TransactionInterface { */ async getFee(): Promise { const data = await this.getData() - return math.div(data?.meta?.fee ?? 0, 10 ** 9) + return fromLamports(data?.meta?.fee ?? 0) } /** diff --git a/packages/networks/solana/src/services/TransactionSigner.ts b/packages/networks/solana/src/services/TransactionSigner.ts index a76019e..5e01680 100644 --- a/packages/networks/solana/src/services/TransactionSigner.ts +++ b/packages/networks/solana/src/services/TransactionSigner.ts @@ -1,20 +1,24 @@ import { Provider } from '../services/Provider.ts' +import { base58Decode } from '@multiplechain/utils' import { Transaction } from '../models/Transaction.ts' import { NftTransaction } from '../models/NftTransaction.ts' import { CoinTransaction } from '../models/CoinTransaction.ts' import { TokenTransaction } from '../models/TokenTransaction.ts' import type { TransactionSignerInterface } from '@multiplechain/types' +import { Keypair, VersionedTransaction, Transaction as RawTransaction } from '@solana/web3.js' + +type SignedTransaction = Buffer | Uint8Array export class TransactionSigner implements TransactionSignerInterface { /** * Transaction data from the blockchain network */ - rawData: any + rawData: RawTransaction /** * Signed transaction data */ - signedData?: any + signedData: SignedTransaction /** * Blockchain network provider @@ -22,9 +26,9 @@ export class TransactionSigner implements TransactionSignerInterface { provider: Provider /** - * @param {any} rawData - Transaction data + * @param {RawTransaction} rawData - Transaction data */ - constructor(rawData: any, provider?: Provider) { + constructor(rawData: RawTransaction, provider?: Provider) { this.rawData = rawData this.provider = provider ?? Provider.instance } @@ -35,7 +39,43 @@ export class TransactionSigner implements TransactionSignerInterface { * @returns {Promise} Signed transaction data */ async sign(privateKey: string): Promise { - return await Promise.resolve(this) + this.rawData.recentBlockhash = ( + await this.provider.web3.getLatestBlockhash('finalized') + ).blockhash + + const serialized = this.rawData.serialize({ + requireAllSignatures: false, + verifySignatures: true + }) + + const feePayer = Keypair.fromSecretKey(base58Decode(privateKey)) + const transaction = this.getRawTransaction(serialized.toString('base64')) + + if (transaction instanceof VersionedTransaction) { + transaction.sign([feePayer]) + } else { + transaction.partialSign(feePayer) + } + + this.signedData = transaction.serialize() + + return this + } + + /** + * Get the raw transaction data + * @returns Transaction data + */ + private getRawTransaction(encodedTransaction: string): RawTransaction | VersionedTransaction { + let recoveredTransaction: RawTransaction | VersionedTransaction + try { + recoveredTransaction = RawTransaction.from(Buffer.from(encodedTransaction, 'base64')) + } catch (error) { + recoveredTransaction = VersionedTransaction.deserialize( + Buffer.from(encodedTransaction, 'base64') + ) + } + return recoveredTransaction } /** @@ -43,14 +83,14 @@ export class TransactionSigner implements TransactionSignerInterface { * @returns {Promise} */ async send(): Promise { - return await Promise.resolve(new Transaction('example')) + return new Transaction(await this.provider.web3.sendRawTransaction(this.signedData)) } /** * Get the raw transaction data * @returns Transaction data */ - getRawData(): any { + getRawData(): RawTransaction { return this.rawData } @@ -58,7 +98,7 @@ export class TransactionSigner implements TransactionSignerInterface { * Get the signed transaction data * @returns Signed transaction data */ - getSignedData(): any { + getSignedData(): SignedTransaction { return this.signedData } } diff --git a/packages/networks/solana/src/utils.ts b/packages/networks/solana/src/utils.ts new file mode 100644 index 0000000..83246b7 --- /dev/null +++ b/packages/networks/solana/src/utils.ts @@ -0,0 +1,11 @@ +import { math } from '@multiplechain/utils' + +export * from '@multiplechain/utils' + +export const fromLamports = (amount: number): number => { + return math.div(amount, 1000000000, 9) +} + +export const toLamports = (amount: number): number => { + return math.mul(amount, 1000000000, 9) +} diff --git a/packages/networks/solana/tests/assets.spec.ts b/packages/networks/solana/tests/assets.spec.ts index 34c5579..4f777e1 100644 --- a/packages/networks/solana/tests/assets.spec.ts +++ b/packages/networks/solana/tests/assets.spec.ts @@ -1,7 +1,94 @@ -import { describe, it, expect } from 'vitest' +import { describe, it, expect, assert } from 'vitest' -describe('example', () => { - it('should work', () => { - expect(1 + 1).toBe(2) +import { NFT } from '../src/assets/NFT.ts' +import { Coin } from '../src/assets/Coin.ts' +import { Token } from '../src/assets/Token.ts' +import { math } from '@multiplechain/utils' +import { Transaction } from '../src/models/Transaction.ts' +import { TransactionStatusEnum } from '@multiplechain/types' +import { TransactionSigner } from '../src/services/TransactionSigner.ts' + +const coinBalanceTestAmount = Number(process.env.SOL_COIN_BALANCE_TEST_AMOUNT) +const tokenBalanceTestAmount = Number(process.env.SOL_TOKEN_BALANCE_TEST_AMOUNT) +const nftBalanceTestAmount = Number(process.env.SOL_NFT_BALANCE_TEST_AMOUNT) +const transferTestAmount = Number(process.env.SOL_TRANSFER_TEST_AMOUNT) +const tokenTransferTestAmount = Number(process.env.SOL_TOKEN_TRANSFER_TEST_AMOUNT) +const tokenApproveTestAmount = Number(process.env.SOL_TOKEN_APPROVE_TEST_AMOUNT) +const nftTransferId = Number(process.env.SOL_NFT_TRANSFER_ID) + +const coinTransferTestIsActive = Boolean(process.env.SOL_COIN_TRANSFER_TEST_IS_ACTIVE !== 'false') +const tokenTransferTestIsActive = Boolean(process.env.SOL_TOKEN_TRANSFER_TEST_IS_ACTIVE !== 'false') +const tokenApproveTestIsActive = Boolean(process.env.SOL_TOKEN_APPROVE_TEST_IS_ACTIVE !== 'false') +const nftTransactionTestIsActive = Boolean( + process.env.SOL_NFT_TRANSACTION_TEST_IS_ACTIVE !== 'false' +) +const tokenTransferFromTestIsActive = Boolean( + process.env.SOL_TOKEN_TRANSFER_FROM_TEST_IS_ACTIVE !== 'false' +) + +const balanceTestAddress = String(process.env.SOL_BALANCE_TEST_ADDRESS) +const senderPrivateKey = String(process.env.SOL_SENDER_PRIVATE_KEY) +const receiverPrivateKey = String(process.env.SOL_RECEIVER_PRIVATE_KEY) +const senderTestAddress = String(process.env.SOL_SENDER_TEST_ADDRESS) +const receiverTestAddress = String(process.env.SOL_RECEIVER_TEST_ADDRESS) +const tokenTestAddress = String(process.env.SOL_TOKEN_TEST_ADDRESS) +const token2022TestAddress = String(process.env.SOL_TOKEN_2022_TEST_ADDRESS) +const nftTestAddress = String(process.env.SOL_NFT_TEST_ADDRESS) + +const waitSecondsBeforeThanNewTx = async (seconds: number): Promise => { + return await new Promise((resolve) => setTimeout(resolve, seconds * 1000)) +} + +const checkSigner = async (signer: TransactionSigner, privateKey?: string): Promise => { + expect(signer).toBeInstanceOf(TransactionSigner) + + const rawData = signer.getRawData() + + assert.isObject(rawData) + + await signer.sign(privateKey ?? senderPrivateKey) + + expect(signer.getSignedData()).toBeInstanceOf(Buffer) +} + +const checkTx = async (transaction: Transaction): Promise => { + expect(transaction).toBeInstanceOf(Transaction) + const status = await transaction.wait(10 * 1000) + expect(status).toBe(TransactionStatusEnum.CONFIRMED) +} + +describe('Coin', () => { + const coin = new Coin() + it('Name and symbol', () => { + expect(coin.getName()).toBe('Solana') + expect(coin.getSymbol()).toBe('SOL') + }) + + it('Decimals', () => { + expect(coin.getDecimals()).toBe(9) + }) + + it('Balance', async () => { + const balance = await coin.getBalance(balanceTestAddress) + expect(balance).toBe(coinBalanceTestAmount) + }) + + it('Transfer', async () => { + const signer = await coin.transfer( + senderTestAddress, + receiverTestAddress, + transferTestAmount + ) + + await checkSigner(signer) + + if (!coinTransferTestIsActive) return + + const beforeBalance = await coin.getBalance(receiverTestAddress) + + await checkTx(await signer.send()) + + const afterBalance = await coin.getBalance(receiverTestAddress) + expect(afterBalance).toBe(math.add(beforeBalance, transferTestAmount)) }) }) From 5ca6d85050eaef8f0d67883adc4169e3adec0397 Mon Sep 17 00:00:00 2001 From: Halil Beycan <50718965+BeycanDeveloper@users.noreply.github.com> Date: Sat, 18 May 2024 17:09:37 +0800 Subject: [PATCH 42/90] token completed --- packages/networks/solana/package.json | 1 + packages/networks/solana/pnpm-lock.yaml | 3 + .../networks/solana/src/assets/Contract.ts | 3 + packages/networks/solana/src/assets/Token.ts | 319 +++++++++++++++++- packages/networks/solana/tests/assets.spec.ts | 153 +++++++++ packages/networks/solana/tests/models.spec.ts | 6 +- 6 files changed, 466 insertions(+), 19 deletions(-) diff --git a/packages/networks/solana/package.json b/packages/networks/solana/package.json index d4f28ef..fa7f4ea 100644 --- a/packages/networks/solana/package.json +++ b/packages/networks/solana/package.json @@ -66,6 +66,7 @@ "@multiplechain/types": "^0.1.55", "@multiplechain/utils": "^0.1.18", "@solana/spl-token": "^0.4.6", + "@solana/spl-token-metadata": "^0.1.4", "@solana/web3.js": "^1.91.8", "axios": "^1.6.8" } diff --git a/packages/networks/solana/pnpm-lock.yaml b/packages/networks/solana/pnpm-lock.yaml index 3789f2e..77b381a 100644 --- a/packages/networks/solana/pnpm-lock.yaml +++ b/packages/networks/solana/pnpm-lock.yaml @@ -17,6 +17,9 @@ dependencies: '@solana/spl-token': specifier: ^0.4.6 version: 0.4.6(@solana/web3.js@1.91.8)(fastestsmallesttextencoderdecoder@1.0.22) + '@solana/spl-token-metadata': + specifier: ^0.1.4 + version: 0.1.4(@solana/web3.js@1.91.8)(fastestsmallesttextencoderdecoder@1.0.22) '@solana/web3.js': specifier: ^1.91.8 version: 1.91.8 diff --git a/packages/networks/solana/src/assets/Contract.ts b/packages/networks/solana/src/assets/Contract.ts index ee3a295..478603d 100644 --- a/packages/networks/solana/src/assets/Contract.ts +++ b/packages/networks/solana/src/assets/Contract.ts @@ -1,3 +1,4 @@ +import { PublicKey } from '@solana/web3.js' import { Provider } from '../services/Provider.ts' import type { ContractInterface } from '@multiplechain/types' @@ -7,6 +8,7 @@ export class Contract implements ContractInterface { */ address: string + pubKey: PublicKey /** * Blockchain network provider */ @@ -18,6 +20,7 @@ export class Contract implements ContractInterface { */ constructor(address: string, provider?: Provider) { this.address = address + this.pubKey = new PublicKey(address) this.provider = provider ?? Provider.instance } diff --git a/packages/networks/solana/src/assets/Token.ts b/packages/networks/solana/src/assets/Token.ts index 8d30a0d..1f62aa6 100644 --- a/packages/networks/solana/src/assets/Token.ts +++ b/packages/networks/solana/src/assets/Token.ts @@ -1,27 +1,103 @@ import { Contract } from './Contract.ts' -import type { TokenInterface } from '@multiplechain/types' +import { math } from '@multiplechain/utils' +import { Metaplex } from '@metaplex-foundation/js' +import { ErrorTypeEnum, type TokenInterface } from '@multiplechain/types' import { TokenTransactionSigner } from '../services/TransactionSigner.ts' +import { + PublicKey, + Transaction, + type AccountInfo, + type ParsedAccountData, + type RpcResponseAndContext +} from '@solana/web3.js' +import { + TOKEN_PROGRAM_ID, + TOKEN_2022_PROGRAM_ID, + getTokenMetadata, + ASSOCIATED_TOKEN_PROGRAM_ID, + getAssociatedTokenAddressSync, + createAssociatedTokenAccountInstruction, + createTransferInstruction, + createApproveInstruction +} from '@solana/spl-token' + +interface Metadata { + name: string + symbol: string + programId: string + decimals: number +} export class Token extends Contract implements TokenInterface { + metadata: Metadata + + /** + * Token metadata + */ + async getMetadata(): Promise { + if (this.metadata !== undefined) return this.metadata + + const accountInfo = (await this.provider.web3.getParsedAccountInfo( + this.pubKey + )) as unknown as RpcResponseAndContext> + + if (accountInfo?.value === null) return null + + const programId = accountInfo.value.owner + + if (TOKEN_2022_PROGRAM_ID.equals(programId)) { + const result = await getTokenMetadata( + this.provider.web3, + this.pubKey, + 'confirmed', + programId + ) + if (result === null) return null + return (this.metadata = { + name: result.name, + symbol: result.symbol, + programId: programId.toBase58(), + decimals: accountInfo.value.data.parsed.info.decimals + }) + } else { + const metaplex = Metaplex.make(this.provider.web3) + const data = await metaplex.nfts().findByMint({ mintAddress: this.pubKey }) + return (this.metadata = { + name: data.name, + symbol: data.symbol, + programId: programId.toBase58(), + decimals: accountInfo.value.data.parsed.info.decimals + }) + } + } + + async getProgramId(): Promise { + const accountInfo = await this.provider.web3.getAccountInfo(this.pubKey) + return accountInfo !== null ? accountInfo.owner : TOKEN_PROGRAM_ID + } + /** * @returns {Promise} Token name */ async getName(): Promise { - return 'example' + await this.getMetadata() + return this.metadata.name } /** * @returns {Promise} Token symbol */ async getSymbol(): Promise { - return 'example' + await this.getMetadata() + return this.metadata.symbol } /** * @returns {Promise} Decimal value of the token */ async getDecimals(): Promise { - return 18 + await this.getMetadata() + return this.metadata.decimals } /** @@ -29,14 +105,20 @@ export class Token extends Contract implements TokenInterface { * @returns {Promise} Wallet balance as currency of TOKEN */ async getBalance(owner: string): Promise { - return 0 + const res = await this.provider.web3.getParsedTokenAccountsByOwner(new PublicKey(owner), { + mint: this.pubKey + }) + + return res.value[0] === undefined + ? 0 + : res.value[0].account.data.parsed.info.tokenAmount.uiAmount } /** * @returns {Promise} Total supply of the token */ async getTotalSupply(): Promise { - return 0 + return (await this.provider.web3.getTokenSupply(this.pubKey)).value.uiAmount ?? 0 } /** @@ -44,8 +126,36 @@ export class Token extends Contract implements TokenInterface { * @param {string} spender Address of the spender that is using the tokens of owner * @returns {Promise} Amount of tokens that the spender is allowed to spend */ - async getAllowance(owner: string, spender: string): Promise { - return 0 + async getAllowance(owner: string, spender?: string): Promise { + const ownerResult = await this.provider.web3.getParsedTokenAccountsByOwner( + new PublicKey(owner), + { + mint: this.pubKey + } + ) + + if (ownerResult.value[0] === undefined) return 0 + + if (ownerResult.value[0].account.data.parsed.info.delegatedAmount === undefined) return 0 + + if (spender !== undefined) { + if ( + ownerResult.value[0].account.data.parsed.info.delegate.toLowerCase() !== + spender.toLowerCase() + ) + return 0 + } + + return ownerResult.value[0].account.data.parsed.info.delegatedAmount.uiAmount + } + + /** + * @param {number} amount Amount of tokens that will be transferred + * @returns {Promise} Formatted amount + */ + private async formatAmount(amount: number): Promise { + const decimals = await this.getDecimals() + return math.mul(amount, math.pow(10, decimals), decimals) } /** @@ -60,7 +170,64 @@ export class Token extends Contract implements TokenInterface { receiver: string, amount: number ): Promise { - return new TokenTransactionSigner('example') + if (amount <= 0) { + throw new Error(ErrorTypeEnum.INVALID_AMOUNT) + } + + const balance = await this.getBalance(sender) + + if (amount > balance) { + throw new Error(ErrorTypeEnum.INSUFFICIENT_BALANCE) + } + + const transaction = new Transaction() + const senderPubKey = new PublicKey(sender) + const receiverPubKey = new PublicKey(receiver) + const programId = await this.getProgramId() + const transferAmount = await this.formatAmount(amount) + + const senderAccount = getAssociatedTokenAddressSync( + this.pubKey, + senderPubKey, + false, + programId + ) + + const receiverAccount = getAssociatedTokenAddressSync( + this.pubKey, + receiverPubKey, + false, + programId + ) + + // If the receiver does not have an associated token account, create one + if ((await this.provider.web3.getAccountInfo(receiverAccount)) === null) { + transaction.add( + createAssociatedTokenAccountInstruction( + senderPubKey, + receiverAccount, + receiverPubKey, + this.pubKey, + programId, + ASSOCIATED_TOKEN_PROGRAM_ID + ) + ) + } + + transaction.add( + createTransferInstruction( + senderAccount, + receiverAccount, + senderPubKey, + transferAmount, + [], + programId + ) + ) + + transaction.feePayer = senderPubKey + + return new TokenTransactionSigner(transaction) } /** @@ -76,7 +243,75 @@ export class Token extends Contract implements TokenInterface { receiver: string, amount: number ): Promise { - return new TokenTransactionSigner('example') + if (amount < 0) { + throw new Error(ErrorTypeEnum.INVALID_AMOUNT) + } + + const balance = await this.getBalance(owner) + + if (amount > balance) { + throw new Error(ErrorTypeEnum.INSUFFICIENT_BALANCE) + } + + const allowance = await this.getAllowance(owner, spender) + + if (allowance === 0) { + throw new Error(ErrorTypeEnum.UNAUTHORIZED_ADDRESS) + } + + if (amount > allowance) { + throw new Error(ErrorTypeEnum.INVALID_AMOUNT) + } + + const transaction = new Transaction() + const ownerPubKey = new PublicKey(owner) + const spenderPubKey = new PublicKey(spender) + const receiverPubKey = new PublicKey(receiver) + const programId = await this.getProgramId() + const transferAmount = await this.formatAmount(amount) + + const ownerAccount = getAssociatedTokenAddressSync( + this.pubKey, + ownerPubKey, + false, + programId + ) + + const receiverAccount = getAssociatedTokenAddressSync( + this.pubKey, + receiverPubKey, + false, + programId + ) + + // If the receiver does not have an associated token account, create one + if ((await this.provider.web3.getAccountInfo(receiverAccount)) === null) { + transaction.add( + createAssociatedTokenAccountInstruction( + spenderPubKey, + receiverAccount, + receiverPubKey, + this.pubKey, + programId, + ASSOCIATED_TOKEN_PROGRAM_ID + ) + ) + } + + transaction.add( + createTransferInstruction( + ownerAccount, + receiverAccount, + spenderPubKey, + transferAmount, + [], + programId + ) + ) + + transaction.feePayer = spenderPubKey + + return new TokenTransactionSigner(transaction) } /** @@ -86,11 +321,63 @@ export class Token extends Contract implements TokenInterface { * @param {number} amount Amount of the tokens that will be used * @returns {Promise} Transaction signer */ - async approve( - owner: string, - spender: string, - amount: number - ): Promise { - return new TokenTransactionSigner('example') + async approve(owner: string, spender: string, amount: number): Promise { + if (amount < 0) { + throw new Error(ErrorTypeEnum.INVALID_AMOUNT) + } + + const balance = await this.getBalance(owner) + + if (amount > balance) { + throw new Error(ErrorTypeEnum.INSUFFICIENT_BALANCE) + } + const transaction = new Transaction() + const ownerPubKey = new PublicKey(owner) + const spenderPubKey = new PublicKey(spender) + const programId = await this.getProgramId() + const approveAmount = await this.formatAmount(amount) + + const ownerAccount = getAssociatedTokenAddressSync( + this.pubKey, + ownerPubKey, + false, + programId + ) + + const spenderAccount = getAssociatedTokenAddressSync( + this.pubKey, + spenderPubKey, + false, + programId + ) + + // If the receiver does not have an associated token account, create one + if ((await this.provider.web3.getAccountInfo(spenderAccount)) === null) { + transaction.add( + createAssociatedTokenAccountInstruction( + ownerPubKey, + spenderAccount, + spenderPubKey, + this.pubKey, + programId, + ASSOCIATED_TOKEN_PROGRAM_ID + ) + ) + } + + transaction.add( + createApproveInstruction( + ownerAccount, + spenderPubKey, + ownerPubKey, + approveAmount, + [], + programId + ) + ) + + transaction.feePayer = ownerPubKey + + return new TokenTransactionSigner(transaction) } } diff --git a/packages/networks/solana/tests/assets.spec.ts b/packages/networks/solana/tests/assets.spec.ts index 4f777e1..a3f1138 100644 --- a/packages/networks/solana/tests/assets.spec.ts +++ b/packages/networks/solana/tests/assets.spec.ts @@ -92,3 +92,156 @@ describe('Coin', () => { expect(afterBalance).toBe(math.add(beforeBalance, transferTestAmount)) }) }) + +describe('Token', async () => { + const token = new Token(tokenTestAddress) + const token2022 = new Token(token2022TestAddress) + + it('Name and symbol', async () => { + expect(await token.getName()).toBe('Example') + expect(await token.getSymbol()).toBe('EXM') + expect(await token2022.getName()).toBe('Example Token 2022') + expect(await token2022.getSymbol()).toBe('EXM2') + }) + + it('Decimals', async () => { + expect(await token.getDecimals()).toBe(8) + expect(await token2022.getDecimals()).toBe(9) + }) + + it('Balance', async () => { + expect(await token.getBalance(balanceTestAddress)).toBe(tokenBalanceTestAmount) + expect(await token2022.getBalance(balanceTestAddress)).toBe(tokenBalanceTestAmount) + }) + + it('Total supply', async () => { + expect(await token.getTotalSupply()).toBe(100000000000) + expect(await token2022.getTotalSupply()).toBe(10000000) + }) + + it('Transfer', async () => { + const signer = await token.transfer( + senderTestAddress, + receiverTestAddress, + tokenTransferTestAmount + ) + + await checkSigner(signer) + + if (!tokenTransferTestIsActive) return + + await waitSecondsBeforeThanNewTx(5) + + const beforeBalance = await token.getBalance(receiverTestAddress) + + await checkTx(await signer.send()) + + const afterBalance = await token.getBalance(receiverTestAddress) + expect(afterBalance).toBe(math.add(beforeBalance, tokenTransferTestAmount)) + }) + + it('Transfer 2022', async () => { + const signer = await token2022.transfer( + senderTestAddress, + receiverTestAddress, + tokenTransferTestAmount + ) + + await checkSigner(signer) + + if (!tokenTransferTestIsActive) return + + await waitSecondsBeforeThanNewTx(5) + + const beforeBalance = await token2022.getBalance(receiverTestAddress) + + await checkTx(await signer.send()) + + const afterBalance = await token2022.getBalance(receiverTestAddress) + expect(afterBalance).toBe(math.add(beforeBalance, tokenTransferTestAmount)) + }) + + it('Approve and Allowance', async () => { + const signer = await token.approve( + senderTestAddress, + receiverTestAddress, + tokenApproveTestAmount + ) + + await checkSigner(signer) + + if (!tokenApproveTestIsActive) return + + await waitSecondsBeforeThanNewTx(5) + + await checkTx(await signer.send()) + + expect(await token.getAllowance(senderTestAddress, receiverTestAddress)).toBe( + tokenApproveTestAmount + ) + }) + + it('Approve and Allowance 2022', async () => { + const signer = await token2022.approve( + senderTestAddress, + receiverTestAddress, + tokenApproveTestAmount + ) + + await checkSigner(signer) + + if (!tokenApproveTestIsActive) return + + await waitSecondsBeforeThanNewTx(5) + + await checkTx(await signer.send()) + + expect(await token.getAllowance(senderTestAddress, receiverTestAddress)).toBe( + tokenApproveTestAmount + ) + }) + + it('Transfer from', async () => { + const signer = await token.transferFrom( + receiverTestAddress, + senderTestAddress, + receiverTestAddress, + 2 + ) + + await checkSigner(signer, receiverPrivateKey) + + if (!tokenTransferFromTestIsActive) return + + await waitSecondsBeforeThanNewTx(5) + + const beforeBalance = await token.getBalance(receiverTestAddress) + + await checkTx(await signer.send()) + + const afterBalance = await token.getBalance(receiverTestAddress) + expect(afterBalance).toBe(math.add(beforeBalance, 2)) + }) + + it('Transfer from 2022', async () => { + const signer = await token2022.transferFrom( + receiverTestAddress, + senderTestAddress, + receiverTestAddress, + 2 + ) + + await checkSigner(signer, receiverPrivateKey) + + if (!tokenTransferFromTestIsActive) return + + await waitSecondsBeforeThanNewTx(5) + + const beforeBalance = await token2022.getBalance(receiverTestAddress) + + await checkTx(await signer.send()) + + const afterBalance = await token2022.getBalance(receiverTestAddress) + expect(afterBalance).toBe(math.add(beforeBalance, 2)) + }) +}) diff --git a/packages/networks/solana/tests/models.spec.ts b/packages/networks/solana/tests/models.spec.ts index e5ea1b6..62c3985 100644 --- a/packages/networks/solana/tests/models.spec.ts +++ b/packages/networks/solana/tests/models.spec.ts @@ -165,9 +165,9 @@ describe('Token Transaction', () => { TransactionStatusEnum.CONFIRMED ) - expect(await tx.verifyTransfer(AssetDirectionEnum.OUTGOING, receiver, tokenAmount)).toBe( - TransactionStatusEnum.FAILED - ) + expect( + await tx2022.verifyTransfer(AssetDirectionEnum.OUTGOING, receiver, tokenAmount) + ).toBe(TransactionStatusEnum.FAILED) }) }) From bce02653b8b1d9b6f9b65cc1867e83e9145f7663 Mon Sep 17 00:00:00 2001 From: Halil Beycan <50718965+BeycanDeveloper@users.noreply.github.com> Date: Sat, 18 May 2024 17:40:27 +0800 Subject: [PATCH 43/90] fixed comment line --- .env.example | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.env.example b/.env.example index a47fcb7..f127fe9 100644 --- a/.env.example +++ b/.env.example @@ -109,7 +109,8 @@ SOL_NFT_BALANCE_TEST_AMOUNT=2 SOL_TRANSFER_TEST_AMOUNT=0.001 SOL_TOKEN_TRANSFER_TEST_AMOUNT=1 SOL_TOKEN_APPROVE_TEST_AMOUNT=10 -SOL_NFT_TRANSFER_ID='FxN19KB5UeZJFwxLFgT57WvYYXYhBFKxVumfq37xU4Ck' #NFT ID +#NFT ID +SOL_NFT_TRANSFER_ID='FxN19KB5UeZJFwxLFgT57WvYYXYhBFKxVumfq37xU4Ck' SOL_BALANCE_TEST_ADDRESS='2i6NifwwBGJKUEhYhqbGwu66kDhbfyjgp7zPN5dQsKsE' SOL_SENDER_PRIVATE_KEY='2hh51RHd1cEgiuEj2azZJFNphh27S8578otEHw8WvUia1yEBaW7o7XNuxdV1qQYbvxL5FHrcHpbZMCCxULTkCHRq' @@ -118,7 +119,8 @@ SOL_SENDER_TEST_ADDRESS='7bn9So6CKmdn2vHYZU5oG6gaVEewW3N7U8vJoNmSv2vB' SOL_RECEIVER_TEST_ADDRESS='GHVMV3zZscR8V4K5GEgQTUjuV4jEixB9a4QX3KhgvVKy' SOL_TOKEN_TEST_ADDRESS='2ZHwL3dXk3szRgiBLZi244NmKs2VmoBx764AYMY2tQfx' SOL_TOKEN_2022_TEST_ADDRESS='FQPbc46pp1b3QWHFJFfsvQrv7YedX8XEum5c18mLnipE' -SOL_NFT_TEST_ADDRESS='9B8bxQWovwm5na85xtDPuAyUVingcVdqWk3d9yQV2zsA' #Collection Mint Address +#Collection Mint Address +SOL_NFT_TEST_ADDRESS='9B8bxQWovwm5na85xtDPuAyUVingcVdqWk3d9yQV2zsA' # Assets # Models From ce8e67162c893f48c16510015ad011ade5a74254 Mon Sep 17 00:00:00 2001 From: Halil Beycan <50718965+BeycanDeveloper@users.noreply.github.com> Date: Sat, 18 May 2024 19:02:37 +0800 Subject: [PATCH 44/90] nft completed --- packages/networks/solana/src/assets/NFT.ts | 194 +++++++++++++++++- packages/networks/solana/tests/assets.spec.ts | 82 +++++++- 2 files changed, 265 insertions(+), 11 deletions(-) diff --git a/packages/networks/solana/src/assets/NFT.ts b/packages/networks/solana/src/assets/NFT.ts index 0a89a51..dca32e6 100644 --- a/packages/networks/solana/src/assets/NFT.ts +++ b/packages/networks/solana/src/assets/NFT.ts @@ -1,20 +1,70 @@ import { Contract } from './Contract.ts' -import type { NftInterface } from '@multiplechain/types' +import { Metaplex } from '@metaplex-foundation/js' +import { ErrorTypeEnum, type NftInterface } from '@multiplechain/types' import { NftTransactionSigner } from '../services/TransactionSigner.ts' +import type { Sft, SftWithToken, Nft, NftWithToken } from '@metaplex-foundation/js' +import { + PublicKey, + Transaction, + type AccountInfo, + type ParsedAccountData, + type RpcResponseAndContext +} from '@solana/web3.js' +import { + TOKEN_PROGRAM_ID, + ASSOCIATED_TOKEN_PROGRAM_ID, + getAssociatedTokenAddressSync, + createAssociatedTokenAccountInstruction, + createTransferInstruction, + createApproveInstruction +} from '@solana/spl-token' + +type Metadata = Sft | SftWithToken | Nft | NftWithToken export class NFT extends Contract implements NftInterface { + metadata: Metadata + + /** + * @param {PublicKey} pubKey + * @returns {Promise} Metadata of the NFT + */ + async getMetadata(pubKey?: PublicKey): Promise { + try { + // if metadata is already fetched and pubKey is not provided, return the metadata + if (this.metadata !== undefined && pubKey === undefined) { + return this.metadata + } + const metaplex = Metaplex.make(this.provider.web3) + return (this.metadata = await metaplex.nfts().findByMint({ + mintAddress: pubKey ?? this.pubKey + })) + } catch (error) { + return null + } + } + + /** + * @param {PublicKey} pubKey Program ID + * @returns {Promise} Program ID + * @throws {Error} If the program ID is not found + */ + async getProgramId(pubKey: PublicKey): Promise { + const accountInfo = await this.provider.web3.getAccountInfo(pubKey) + return accountInfo !== null ? accountInfo.owner : TOKEN_PROGRAM_ID + } + /** * @returns {Promise} NFT name */ async getName(): Promise { - return 'example' + return (await this.getMetadata())?.name ?? '' } /** * @returns {Promise} NFT symbol */ async getSymbol(): Promise { - return 'example' + return (await this.getMetadata())?.symbol ?? '' } /** @@ -22,7 +72,12 @@ export class NFT extends Contract implements NftInterface { * @returns {Promise} Wallet balance as currency of NFT */ async getBalance(owner: string): Promise { - return 0 + const metaplex = Metaplex.make(this.provider.web3) + const res = await metaplex.nfts().findAllByOwner({ owner: new PublicKey(owner) }) + return res.filter((nft) => { + if (nft.collection?.address === undefined) return false + return this.pubKey.equals(nft.collection?.address) + }).length } /** @@ -30,7 +85,11 @@ export class NFT extends Contract implements NftInterface { * @returns {Promise} Wallet address of the owner of the NFT */ async getOwner(nftId: number | string): Promise { - return 'example' + const accounts = await this.provider.web3.getTokenLargestAccounts(new PublicKey(nftId)) + const accountInfo = (await this.provider.web3.getParsedAccountInfo( + accounts.value[0].address + )) as unknown as RpcResponseAndContext> + return accountInfo.value.data.parsed.info.owner } /** @@ -38,7 +97,7 @@ export class NFT extends Contract implements NftInterface { * @returns {Promise} URI of the NFT */ async getTokenURI(nftId: number | string): Promise { - return 'example' + return (await this.getMetadata(new PublicKey(nftId)))?.uri ?? '' } /** @@ -46,7 +105,11 @@ export class NFT extends Contract implements NftInterface { * @returns {Promise} Wallet address of the approved spender */ async getApproved(nftId: number | string): Promise { - return 'example' + const accounts = await this.provider.web3.getTokenLargestAccounts(new PublicKey(nftId)) + const accountInfo = (await this.provider.web3.getParsedAccountInfo( + accounts.value[0].address + )) as unknown as RpcResponseAndContext> + return accountInfo.value.data.parsed.info.delegate ?? null } /** @@ -60,7 +123,7 @@ export class NFT extends Contract implements NftInterface { receiver: string, nftId: number | string ): Promise { - return new NftTransactionSigner('example') + return await this.transferFrom(sender, sender, receiver, nftId) } /** @@ -76,7 +139,70 @@ export class NFT extends Contract implements NftInterface { receiver: string, nftId: number | string ): Promise { - return new NftTransactionSigner('example') + // Check if tokens exist + const balance = await this.getBalance(owner) + + if (balance <= 0) { + throw new Error(ErrorTypeEnum.INSUFFICIENT_BALANCE) + } + + // Check ownership + const originalOwner = await this.getOwner(nftId) + if (originalOwner !== owner) { + throw new Error(ErrorTypeEnum.UNAUTHORIZED_ADDRESS) + } + + // check if spender different from owner + if (spender !== owner) { + const approved = await this.getApproved(nftId) + if (approved !== spender) { + throw new Error(ErrorTypeEnum.UNAUTHORIZED_ADDRESS) + } + } + + const nftPubKey = new PublicKey(nftId) + const transaction = new Transaction() + const ownerPubKey = new PublicKey(owner) + const spenderPubKey = new PublicKey(spender) + const receiverPubKey = new PublicKey(receiver) + const programId = await this.getProgramId(nftPubKey) + + const ownerAccount = getAssociatedTokenAddressSync(nftPubKey, ownerPubKey, false, programId) + + const receiverAccount = getAssociatedTokenAddressSync( + nftPubKey, + receiverPubKey, + false, + programId + ) + // If the receiver does not have an associated token account, create one + if ((await this.provider.web3.getAccountInfo(receiverAccount)) === null) { + transaction.add( + createAssociatedTokenAccountInstruction( + spenderPubKey, + receiverAccount, + receiverPubKey, + nftPubKey, + programId, + ASSOCIATED_TOKEN_PROGRAM_ID + ) + ) + } + + transaction.add( + createTransferInstruction( + ownerAccount, + receiverAccount, + spenderPubKey, + 1, + [], + programId + ) + ) + + transaction.feePayer = spenderPubKey + + return new NftTransactionSigner(transaction) } /** @@ -91,6 +217,54 @@ export class NFT extends Contract implements NftInterface { spender: string, nftId: number | string ): Promise { - return new NftTransactionSigner('example') + // Check if tokens exist + const balance = await this.getBalance(owner) + + if (balance <= 0) { + throw new Error(ErrorTypeEnum.INSUFFICIENT_BALANCE) + } + + // Check ownership + const originalOwner = await this.getOwner(nftId) + if (originalOwner !== owner) { + throw new Error(ErrorTypeEnum.UNAUTHORIZED_ADDRESS) + } + + const transaction = new Transaction() + const nftPubKey = new PublicKey(nftId) + const ownerPubKey = new PublicKey(owner) + const spenderPubKey = new PublicKey(spender) + const programId = await this.getProgramId(nftPubKey) + + const ownerAccount = getAssociatedTokenAddressSync(nftPubKey, ownerPubKey, false, programId) + + const spenderAccount = getAssociatedTokenAddressSync( + nftPubKey, + spenderPubKey, + false, + programId + ) + + // If the receiver does not have an associated token account, create one + if ((await this.provider.web3.getAccountInfo(spenderAccount)) === null) { + transaction.add( + createAssociatedTokenAccountInstruction( + ownerPubKey, + spenderAccount, + spenderPubKey, + this.pubKey, + programId, + ASSOCIATED_TOKEN_PROGRAM_ID + ) + ) + } + + transaction.add( + createApproveInstruction(ownerAccount, spenderPubKey, ownerPubKey, 1, [], programId) + ) + + transaction.feePayer = ownerPubKey + + return new NftTransactionSigner(transaction) } } diff --git a/packages/networks/solana/tests/assets.spec.ts b/packages/networks/solana/tests/assets.spec.ts index a3f1138..680d8de 100644 --- a/packages/networks/solana/tests/assets.spec.ts +++ b/packages/networks/solana/tests/assets.spec.ts @@ -14,7 +14,7 @@ const nftBalanceTestAmount = Number(process.env.SOL_NFT_BALANCE_TEST_AMOUNT) const transferTestAmount = Number(process.env.SOL_TRANSFER_TEST_AMOUNT) const tokenTransferTestAmount = Number(process.env.SOL_TOKEN_TRANSFER_TEST_AMOUNT) const tokenApproveTestAmount = Number(process.env.SOL_TOKEN_APPROVE_TEST_AMOUNT) -const nftTransferId = Number(process.env.SOL_NFT_TRANSFER_ID) +const nftTransferId = String(process.env.SOL_NFT_TRANSFER_ID) const coinTransferTestIsActive = Boolean(process.env.SOL_COIN_TRANSFER_TEST_IS_ACTIVE !== 'false') const tokenTransferTestIsActive = Boolean(process.env.SOL_TOKEN_TRANSFER_TEST_IS_ACTIVE !== 'false') @@ -245,3 +245,83 @@ describe('Token', async () => { expect(afterBalance).toBe(math.add(beforeBalance, 2)) }) }) + +describe('Nft', async () => { + const nft = new NFT(nftTestAddress) + const id = 'F8kj1xPSG69amgDS7XfmkHgAAWgiJ391NFTkxJL2e5Di' + + it('Name and symbol', async () => { + expect(await nft.getName()).toBe('Test NFT Collection') + expect(await nft.getSymbol()).toBe('TNFT') + }) + + it('Balance', async () => { + const balance = await nft.getBalance(balanceTestAddress) + expect(balance).toBe(nftBalanceTestAmount) + }) + + it('Owner', async () => { + expect(await nft.getOwner(id)).toBe(balanceTestAddress) + }) + + it('Token URI', async () => { + expect(await nft.getTokenURI(id)).toBe( + 'https://arweave.net/8SvLYJ8CgpxzihKD2r-DKRmjPlyxa_WGeuA8ARI0ems' + ) + }) + + it('Approved', async () => { + expect(await nft.getApproved(id)).toBe(null) + }) + + it('Transfer', async () => { + const signer = await nft.transfer(senderTestAddress, receiverTestAddress, nftTransferId) + + await checkSigner(signer) + + if (!nftTransactionTestIsActive) return + + await waitSecondsBeforeThanNewTx(5) + + await checkTx(await signer.send()) + + expect(await nft.getOwner(nftTransferId)).toBe(receiverTestAddress) + }) + + it('Approve', async () => { + const customOwner = nftTransactionTestIsActive ? receiverTestAddress : senderTestAddress + const customSpender = nftTransactionTestIsActive ? senderTestAddress : receiverTestAddress + const customPrivateKey = nftTransactionTestIsActive ? receiverPrivateKey : senderPrivateKey + + const signer = await nft.approve(customOwner, customSpender, nftTransferId) + + await checkSigner(signer, customPrivateKey) + + if (!nftTransactionTestIsActive) return + + await waitSecondsBeforeThanNewTx(5) + + await checkTx(await signer.send()) + + expect(await nft.getApproved(nftTransferId)).toBe(senderTestAddress) + }) + + it('Transfer from', async () => { + if (!nftTransactionTestIsActive) return + + await waitSecondsBeforeThanNewTx(5) + + const signer = await nft.transferFrom( + senderTestAddress, + receiverTestAddress, + senderTestAddress, + nftTransferId + ) + + await checkSigner(signer) + + await checkTx(await signer.send()) + + expect(await nft.getOwner(nftTransferId)).toBe(senderTestAddress) + }) +}) From 2762c3fcbf834b0d931cce5bb456c9962ac6acc5 Mon Sep 17 00:00:00 2001 From: Halil Beycan <50718965+BeycanDeveloper@users.noreply.github.com> Date: Sat, 18 May 2024 19:33:58 +0800 Subject: [PATCH 45/90] moved transfer to transferFrom --- packages/networks/solana/src/assets/Token.ts | 75 +++----------------- 1 file changed, 11 insertions(+), 64 deletions(-) diff --git a/packages/networks/solana/src/assets/Token.ts b/packages/networks/solana/src/assets/Token.ts index 1f62aa6..5a2992d 100644 --- a/packages/networks/solana/src/assets/Token.ts +++ b/packages/networks/solana/src/assets/Token.ts @@ -170,64 +170,7 @@ export class Token extends Contract implements TokenInterface { receiver: string, amount: number ): Promise { - if (amount <= 0) { - throw new Error(ErrorTypeEnum.INVALID_AMOUNT) - } - - const balance = await this.getBalance(sender) - - if (amount > balance) { - throw new Error(ErrorTypeEnum.INSUFFICIENT_BALANCE) - } - - const transaction = new Transaction() - const senderPubKey = new PublicKey(sender) - const receiverPubKey = new PublicKey(receiver) - const programId = await this.getProgramId() - const transferAmount = await this.formatAmount(amount) - - const senderAccount = getAssociatedTokenAddressSync( - this.pubKey, - senderPubKey, - false, - programId - ) - - const receiverAccount = getAssociatedTokenAddressSync( - this.pubKey, - receiverPubKey, - false, - programId - ) - - // If the receiver does not have an associated token account, create one - if ((await this.provider.web3.getAccountInfo(receiverAccount)) === null) { - transaction.add( - createAssociatedTokenAccountInstruction( - senderPubKey, - receiverAccount, - receiverPubKey, - this.pubKey, - programId, - ASSOCIATED_TOKEN_PROGRAM_ID - ) - ) - } - - transaction.add( - createTransferInstruction( - senderAccount, - receiverAccount, - senderPubKey, - transferAmount, - [], - programId - ) - ) - - transaction.feePayer = senderPubKey - - return new TokenTransactionSigner(transaction) + return await this.transferFrom(sender, sender, receiver, amount) } /** @@ -253,14 +196,17 @@ export class Token extends Contract implements TokenInterface { throw new Error(ErrorTypeEnum.INSUFFICIENT_BALANCE) } - const allowance = await this.getAllowance(owner, spender) + // check if spender different from owner + if (spender !== owner) { + const allowance = await this.getAllowance(owner, spender) - if (allowance === 0) { - throw new Error(ErrorTypeEnum.UNAUTHORIZED_ADDRESS) - } + if (allowance === 0) { + throw new Error(ErrorTypeEnum.UNAUTHORIZED_ADDRESS) + } - if (amount > allowance) { - throw new Error(ErrorTypeEnum.INVALID_AMOUNT) + if (amount > allowance) { + throw new Error(ErrorTypeEnum.INVALID_AMOUNT) + } } const transaction = new Transaction() @@ -331,6 +277,7 @@ export class Token extends Contract implements TokenInterface { if (amount > balance) { throw new Error(ErrorTypeEnum.INSUFFICIENT_BALANCE) } + const transaction = new Transaction() const ownerPubKey = new PublicKey(owner) const spenderPubKey = new PublicKey(spender) From 11901ee107166434a30830103fb0a65262f7dbce Mon Sep 17 00:00:00 2001 From: Halil Beycan <50718965+BeycanDeveloper@users.noreply.github.com> Date: Sat, 18 May 2024 19:39:59 +0800 Subject: [PATCH 46/90] removed create token account instruction --- packages/networks/solana/src/assets/NFT.ts | 21 -------------------- packages/networks/solana/src/assets/Token.ts | 21 -------------------- 2 files changed, 42 deletions(-) diff --git a/packages/networks/solana/src/assets/NFT.ts b/packages/networks/solana/src/assets/NFT.ts index dca32e6..954a00c 100644 --- a/packages/networks/solana/src/assets/NFT.ts +++ b/packages/networks/solana/src/assets/NFT.ts @@ -238,27 +238,6 @@ export class NFT extends Contract implements NftInterface { const ownerAccount = getAssociatedTokenAddressSync(nftPubKey, ownerPubKey, false, programId) - const spenderAccount = getAssociatedTokenAddressSync( - nftPubKey, - spenderPubKey, - false, - programId - ) - - // If the receiver does not have an associated token account, create one - if ((await this.provider.web3.getAccountInfo(spenderAccount)) === null) { - transaction.add( - createAssociatedTokenAccountInstruction( - ownerPubKey, - spenderAccount, - spenderPubKey, - this.pubKey, - programId, - ASSOCIATED_TOKEN_PROGRAM_ID - ) - ) - } - transaction.add( createApproveInstruction(ownerAccount, spenderPubKey, ownerPubKey, 1, [], programId) ) diff --git a/packages/networks/solana/src/assets/Token.ts b/packages/networks/solana/src/assets/Token.ts index 5a2992d..10c65ac 100644 --- a/packages/networks/solana/src/assets/Token.ts +++ b/packages/networks/solana/src/assets/Token.ts @@ -291,27 +291,6 @@ export class Token extends Contract implements TokenInterface { programId ) - const spenderAccount = getAssociatedTokenAddressSync( - this.pubKey, - spenderPubKey, - false, - programId - ) - - // If the receiver does not have an associated token account, create one - if ((await this.provider.web3.getAccountInfo(spenderAccount)) === null) { - transaction.add( - createAssociatedTokenAccountInstruction( - ownerPubKey, - spenderAccount, - spenderPubKey, - this.pubKey, - programId, - ASSOCIATED_TOKEN_PROGRAM_ID - ) - ) - } - transaction.add( createApproveInstruction( ownerAccount, From 6520f82a66f39b6df0c3fff8769af75eb863941a Mon Sep 17 00:00:00 2001 From: Halil Beycan <50718965+BeycanDeveloper@users.noreply.github.com> Date: Sat, 18 May 2024 19:50:33 +0800 Subject: [PATCH 47/90] added throws --- .../networks/solana/src/assets/Contract.ts | 26 +++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/packages/networks/solana/src/assets/Contract.ts b/packages/networks/solana/src/assets/Contract.ts index 478603d..f3e0c35 100644 --- a/packages/networks/solana/src/assets/Contract.ts +++ b/packages/networks/solana/src/assets/Contract.ts @@ -32,30 +32,30 @@ export class Contract implements ContractInterface { } /** - * @param {string} method Method name - * @param {any[]} args Method parameters + * @param {string} _method Method name + * @param {any[]} _args Method parameters * @returns {Promise} Method result */ - async callMethod(method: string, ...args: any[]): Promise { - return {} + async callMethod(_method: string, ..._args: any[]): Promise { + throw new Error('Method not implemented.') } /** - * @param {string} method Method name - * @param {any[]} args Sender wallet address + * @param {string} _method Method name + * @param {any[]} _args Sender wallet address * @returns {Promise} Encoded method data */ - async getMethodData(method: string, ...args: any[]): Promise { - return {} + async getMethodData(_method: string, ..._args: any[]): Promise { + throw new Error('Method not implemented.') } /** - * @param {string} method Method name - * @param {string} from Sender wallet address - * @param {any[]} args Method parameters + * @param {string} _method Method name + * @param {string} _from Sender wallet address + * @param {any[]} _args Method parameters * @returns {Promise} Encoded method data */ - async createTransactionData(method: string, from: string, ...args: any[]): Promise { - return '' + async createTransactionData(_method: string, _from: string, ..._args: any[]): Promise { + throw new Error('Method not implemented.') } } From 4ba66d9e55c1cc8a838e6d720814c0c6d1a72859 Mon Sep 17 00:00:00 2001 From: Halil Beycan <50718965+BeycanDeveloper@users.noreply.github.com> Date: Sat, 18 May 2024 20:36:15 +0800 Subject: [PATCH 48/90] general listener completed --- .../networks/solana/src/services/Provider.ts | 4 +- .../src/services/TransactionListener.ts | 42 ++++++++++++++++++- 2 files changed, 43 insertions(+), 3 deletions(-) diff --git a/packages/networks/solana/src/services/Provider.ts b/packages/networks/solana/src/services/Provider.ts index 190cc47..717de6c 100644 --- a/packages/networks/solana/src/services/Provider.ts +++ b/packages/networks/solana/src/services/Provider.ts @@ -135,7 +135,9 @@ export class Provider implements ProviderInterface { this.node = this.nodes[network.testnet ?? false ? 'devnet' : 'mainnet'] this.node.rpcUrl = this.network.rpcUrl ?? this.node.rpcUrl this.node.wsUrl = this.network.wsUrl ?? this.node.wsUrl - this.web3 = new Connection(this.node.rpcUrl, 'recent') + this.web3 = new Connection(this.node.rpcUrl, { + wsEndpoint: this.node.wsUrl + }) } /** diff --git a/packages/networks/solana/src/services/TransactionListener.ts b/packages/networks/solana/src/services/TransactionListener.ts index da72fc3..ada08fe 100644 --- a/packages/networks/solana/src/services/TransactionListener.ts +++ b/packages/networks/solana/src/services/TransactionListener.ts @@ -7,6 +7,8 @@ import type { } from '@multiplechain/types' import { Provider } from './Provider.ts' +import { Transaction } from '../models/Transaction.ts' +import { PublicKey, type LogsFilter } from '@solana/web3.js' import { TransactionListenerProcessIndex } from '@multiplechain/types' export class TransactionListener @@ -37,6 +39,16 @@ export class TransactionListener */ status: boolean = false + /** + * Connected status + */ + connected: boolean = false + + /** + * Dynamic stop method + */ + dynamicStop: () => void = () => {} + /** * Triggered transactions */ @@ -60,7 +72,7 @@ export class TransactionListener stop(): void { if (this.status) { this.status = false - // stop the listener + this.dynamicStop() } } @@ -90,7 +102,17 @@ export class TransactionListener * @returns {Promise} */ async on(callback: TransactionListenerCallbackType): Promise { + if (!this.connected) { + if ((await this.provider.checkWsConnection()) instanceof Error) { + throw new Error('WebSocket connection is not available') + } else { + this.connected = true + } + } + + this.start() this.callbacks.push(callback) + return true } @@ -113,7 +135,23 @@ export class TransactionListener * @returns {void} */ generalProcess(): void { - // General transaction process + let parameter: LogsFilter = 'all' + + if (this.filter?.signer !== undefined) { + parameter = new PublicKey(this.filter.signer) + } + + const subscriptionId = this.provider.web3.onLogs( + parameter, + (logs) => { + this.trigger(new Transaction(logs.signature)) + }, + 'recent' + ) + + this.dynamicStop = () => { + void this.provider.web3.removeOnLogsListener(subscriptionId) + } } /** From 2e223f5f810e070b36002408cfbaab75de532afc Mon Sep 17 00:00:00 2001 From: Halil Beycan <50718965+BeycanDeveloper@users.noreply.github.com> Date: Mon, 20 May 2024 14:36:22 +0800 Subject: [PATCH 49/90] general process fixed --- .../src/services/TransactionListener.ts | 52 ++++++++++++++----- 1 file changed, 39 insertions(+), 13 deletions(-) diff --git a/packages/networks/solana/src/services/TransactionListener.ts b/packages/networks/solana/src/services/TransactionListener.ts index ada08fe..dbab2d6 100644 --- a/packages/networks/solana/src/services/TransactionListener.ts +++ b/packages/networks/solana/src/services/TransactionListener.ts @@ -7,8 +7,8 @@ import type { } from '@multiplechain/types' import { Provider } from './Provider.ts' +import { PublicKey } from '@solana/web3.js' import { Transaction } from '../models/Transaction.ts' -import { PublicKey, type LogsFilter } from '@solana/web3.js' import { TransactionListenerProcessIndex } from '@multiplechain/types' export class TransactionListener @@ -135,20 +135,46 @@ export class TransactionListener * @returns {void} */ generalProcess(): void { - let parameter: LogsFilter = 'all' - - if (this.filter?.signer !== undefined) { - parameter = new PublicKey(this.filter.signer) + let subscriptionId: number + + if (this.filter?.signer === undefined) { + subscriptionId = this.provider.web3.onLogs( + 'all', + (logs) => { + this.trigger(new Transaction(logs.signature)) + }, + 'recent' + ) + } else { + const signer = new PublicKey(this.filter.signer) + subscriptionId = this.provider.web3.onLogs( + signer, + async (logs) => { + try { + const transaction = new Transaction(logs.signature) + const data = await transaction.getData() + + if (data === null) { + return + } + + const isSigner = data.transaction.message.accountKeys.find((account) => { + return account.signer && account.pubkey.equals(signer) + }) + + if (isSigner === undefined) { + return + } + + this.trigger(transaction) + } catch (error) { + // Maybe in future, we can add logging system + } + }, + 'confirmed' + ) } - const subscriptionId = this.provider.web3.onLogs( - parameter, - (logs) => { - this.trigger(new Transaction(logs.signature)) - }, - 'recent' - ) - this.dynamicStop = () => { void this.provider.web3.removeOnLogsListener(subscriptionId) } From 2be31c9c6bdd4edb0c2a56a3448a88e0211f9915 Mon Sep 17 00:00:00 2001 From: Halil Beycan <50718965+BeycanDeveloper@users.noreply.github.com> Date: Mon, 20 May 2024 15:04:48 +0800 Subject: [PATCH 50/90] completed contract listener --- .../src/services/TransactionListener.ts | 61 ++++++++++++++++++- 1 file changed, 59 insertions(+), 2 deletions(-) diff --git a/packages/networks/solana/src/services/TransactionListener.ts b/packages/networks/solana/src/services/TransactionListener.ts index dbab2d6..7e65b76 100644 --- a/packages/networks/solana/src/services/TransactionListener.ts +++ b/packages/networks/solana/src/services/TransactionListener.ts @@ -7,7 +7,7 @@ import type { } from '@multiplechain/types' import { Provider } from './Provider.ts' -import { PublicKey } from '@solana/web3.js' +import { PublicKey, type Logs } from '@solana/web3.js' import { Transaction } from '../models/Transaction.ts' import { TransactionListenerProcessIndex } from '@multiplechain/types' @@ -185,7 +185,64 @@ export class TransactionListener * @returns {void} */ contractProcess(): void { - // Contract transaction process + const filter = this + .filter as DynamicTransactionListenerFilterType + + const callback = async (logs: Logs): Promise => { + try { + const transaction = new Transaction(logs.signature) + const data = await transaction.getData() + + if (data === null) { + return + } + + const isSystemProgram = data.transaction.message.instructions.find( + (instruction) => { + return instruction.programId.equals( + new PublicKey('11111111111111111111111111111111') + ) + } + ) + + if (isSystemProgram !== undefined) { + return + } + + if (filter?.signer !== undefined) { + const signer = new PublicKey(filter.signer) + const isSigner = data.transaction.message.accountKeys.find((account) => { + return account.signer && account.pubkey.equals(new PublicKey(signer)) + }) + + if (isSigner === undefined) { + return + } + } + + if (filter?.address !== undefined) { + const address = new PublicKey(filter.address) + const isProgram = data.transaction.message.instructions.find((instruction) => { + return instruction.programId.equals(address) + }) + + if (isProgram === undefined) { + return + } + } + + this.trigger(transaction) + } catch (error) { + // Maybe in future, we can add logging system + } + } + + const parameter = filter.signer === undefined ? 'all' : new PublicKey(filter.signer) + const subscriptionId = this.provider.web3.onLogs(parameter, callback, 'confirmed') + + this.dynamicStop = () => { + void this.provider.web3.removeOnLogsListener(subscriptionId) + } } /** From 142291e8f61bd3a2ba8eb4e5b44964f7c0d9ce61 Mon Sep 17 00:00:00 2001 From: Halil Beycan <50718965+BeycanDeveloper@users.noreply.github.com> Date: Mon, 20 May 2024 15:40:18 +0800 Subject: [PATCH 51/90] added createAccount handler --- .../solana/src/models/CoinTransaction.ts | 24 +++++++++++++------ 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/packages/networks/solana/src/models/CoinTransaction.ts b/packages/networks/solana/src/models/CoinTransaction.ts index 379f476..1adc260 100644 --- a/packages/networks/solana/src/models/CoinTransaction.ts +++ b/packages/networks/solana/src/models/CoinTransaction.ts @@ -8,10 +8,16 @@ export class CoinTransaction extends Transaction implements CoinTransactionInter /** * @returns {Promise} Wallet address of the receiver of transaction */ - findTransferInstruction(data: any): ParsedInstruction { - return data.transaction.message.instructions.find((instruction: any): boolean => { - return instruction.parsed !== undefined && instruction.parsed.type === 'transfer' - }) as ParsedInstruction + findTransferInstruction(data: any): ParsedInstruction | null { + return ( + (data.transaction.message.instructions.find((instruction: any): boolean => { + return ( + instruction.parsed !== undefined && + (instruction.parsed.type === 'transfer' || + instruction.parsed.type === 'createAccount') + ) + }) as ParsedInstruction) ?? null + ) } /** @@ -23,7 +29,9 @@ export class CoinTransaction extends Transaction implements CoinTransactionInter return '' } - return this.findTransferInstruction(data).parsed.info.destination + const instruction = this.findTransferInstruction(data) + + return instruction?.parsed.info.destination ?? instruction?.parsed.info.newAccount ?? '' } /** @@ -35,7 +43,7 @@ export class CoinTransaction extends Transaction implements CoinTransactionInter return '' } - return this.findTransferInstruction(data).parsed.info.source + return this.findTransferInstruction(data)?.parsed.info.source ?? '' } /** @@ -47,7 +55,9 @@ export class CoinTransaction extends Transaction implements CoinTransactionInter return 0 } - return fromLamports(this.findTransferInstruction(data).parsed.info.lamports as number) + return fromLamports( + (this.findTransferInstruction(data)?.parsed.info.lamports as number) ?? 0 + ) } /** From 98d8e733e7a0adf663e6e2fd64caa2b65f243f50 Mon Sep 17 00:00:00 2001 From: Halil Beycan <50718965+BeycanDeveloper@users.noreply.github.com> Date: Mon, 20 May 2024 16:09:02 +0800 Subject: [PATCH 52/90] coin process completed --- .../src/services/TransactionListener.ts | 106 ++++++++++++++++-- 1 file changed, 94 insertions(+), 12 deletions(-) diff --git a/packages/networks/solana/src/services/TransactionListener.ts b/packages/networks/solana/src/services/TransactionListener.ts index 7e65b76..ec8e85f 100644 --- a/packages/networks/solana/src/services/TransactionListener.ts +++ b/packages/networks/solana/src/services/TransactionListener.ts @@ -7,9 +7,17 @@ import type { } from '@multiplechain/types' import { Provider } from './Provider.ts' -import { PublicKey, type Logs } from '@solana/web3.js' import { Transaction } from '../models/Transaction.ts' +import { + PublicKey, + SystemProgram, + type Logs, + type ParsedInstruction, + type PartiallyDecodedInstruction +} from '@solana/web3.js' import { TransactionListenerProcessIndex } from '@multiplechain/types' +import { ContractTransaction } from '../models/ContractTransaction.ts' +import { CoinTransaction } from '../models/CoinTransaction.ts' export class TransactionListener implements TransactionListenerInterface @@ -180,6 +188,20 @@ export class TransactionListener } } + /** + * @param {(ParsedInstruction | PartiallyDecodedInstruction)[]} instructions + * @returns {boolean} + */ + private isSystemProgram( + instructions: Array + ): boolean { + return Boolean( + instructions.find((instruction) => { + return instruction.programId.equals(SystemProgram.programId) + }) + ) + } + /** * Contract transaction process * @returns {void} @@ -190,22 +212,14 @@ export class TransactionListener const callback = async (logs: Logs): Promise => { try { - const transaction = new Transaction(logs.signature) + const transaction = new ContractTransaction(logs.signature) const data = await transaction.getData() if (data === null) { return } - const isSystemProgram = data.transaction.message.instructions.find( - (instruction) => { - return instruction.programId.equals( - new PublicKey('11111111111111111111111111111111') - ) - } - ) - - if (isSystemProgram !== undefined) { + if (this.isSystemProgram(data.transaction.message.instructions)) { return } @@ -250,7 +264,75 @@ export class TransactionListener * @returns {void} */ coinProcess(): void { - // Coin transaction process + const filter = this.filter as DynamicTransactionListenerFilterType + + if ( + filter.signer !== undefined && + filter.sender !== undefined && + filter.signer !== filter.sender + ) { + throw new Error( + 'Sender and signer must be the same in coin transactions. Or only one of them can be defined.' + ) + } + + const sender = filter.sender ?? filter.signer + const parameter = new PublicKey( + sender ?? filter.receiver ?? SystemProgram.programId.toBase58() + ) + + const callback = async (logs: Logs): Promise => { + try { + const transaction = new CoinTransaction(logs.signature) + const data = await transaction.getData() + + if (data === null) { + return + } + + if (!this.isSystemProgram(data.transaction.message.instructions)) { + return + } + + if (sender !== undefined) { + const isSender = data.transaction.message.accountKeys.find((account) => { + return account.signer && account.pubkey.equals(new PublicKey(sender)) + }) + + if (isSender === undefined) { + return + } + } + + if (filter.receiver !== undefined) { + const receiver = new PublicKey(filter.receiver) + const isReceiver = data.transaction.message.accountKeys.find((account) => { + return account.pubkey.equals(receiver) + }) + + if (isReceiver === undefined) { + return + } + } + + if ( + filter.amount !== undefined && + (await transaction.getAmount()) !== filter.amount + ) { + return + } + + this.trigger(transaction) + } catch (error) { + // Maybe in future, we can add logging system + } + } + + const subscriptionId = this.provider.web3.onLogs(parameter, callback, 'confirmed') + + this.dynamicStop = () => { + void this.provider.web3.removeOnLogsListener(subscriptionId) + } } /** From a0ad873872f615079f5e67f1ab70d196b8e88d81 Mon Sep 17 00:00:00 2001 From: Halil Beycan <50718965+BeycanDeveloper@users.noreply.github.com> Date: Mon, 20 May 2024 16:25:39 +0800 Subject: [PATCH 53/90] updated for find signer --- packages/networks/solana/src/models/Transaction.ts | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/packages/networks/solana/src/models/Transaction.ts b/packages/networks/solana/src/models/Transaction.ts index 98f86df..061d01c 100644 --- a/packages/networks/solana/src/models/Transaction.ts +++ b/packages/networks/solana/src/models/Transaction.ts @@ -104,7 +104,13 @@ export class Transaction implements TransactionInterface { */ async getSigner(): Promise { const data = await this.getData() - return data?.transaction?.message?.accountKeys[0].pubkey.toBase58() ?? '' + return ( + data?.transaction?.message?.accountKeys + .find((account) => { + return account.signer + }) + ?.pubkey.toBase58() ?? '' + ) } /** From b20982d36df5e969035d82c431228fc243a75cec Mon Sep 17 00:00:00 2001 From: Halil Beycan <50718965+BeycanDeveloper@users.noreply.github.com> Date: Mon, 20 May 2024 16:27:48 +0800 Subject: [PATCH 54/90] optimized --- .../src/services/TransactionListener.ts | 100 ++++++++---------- 1 file changed, 47 insertions(+), 53 deletions(-) diff --git a/packages/networks/solana/src/services/TransactionListener.ts b/packages/networks/solana/src/services/TransactionListener.ts index ec8e85f..eaddab2 100644 --- a/packages/networks/solana/src/services/TransactionListener.ts +++ b/packages/networks/solana/src/services/TransactionListener.ts @@ -18,6 +18,7 @@ import { import { TransactionListenerProcessIndex } from '@multiplechain/types' import { ContractTransaction } from '../models/ContractTransaction.ts' import { CoinTransaction } from '../models/CoinTransaction.ts' +import { objectsEqual } from '@multiplechain/utils' export class TransactionListener implements TransactionListenerInterface @@ -154,9 +155,9 @@ export class TransactionListener 'recent' ) } else { - const signer = new PublicKey(this.filter.signer) + const signer = this.filter.signer subscriptionId = this.provider.web3.onLogs( - signer, + new PublicKey(signer), async (logs) => { try { const transaction = new Transaction(logs.signature) @@ -166,11 +167,9 @@ export class TransactionListener return } - const isSigner = data.transaction.message.accountKeys.find((account) => { - return account.signer && account.pubkey.equals(signer) - }) - - if (isSigner === undefined) { + if ( + signer.toLowerCase() !== (await transaction.getSigner()).toLowerCase() + ) { return } @@ -223,26 +222,26 @@ export class TransactionListener return } - if (filter?.signer !== undefined) { - const signer = new PublicKey(filter.signer) - const isSigner = data.transaction.message.accountKeys.find((account) => { - return account.signer && account.pubkey.equals(new PublicKey(signer)) - }) + interface ParamsType { + signer?: string + address?: string + } - if (isSigner === undefined) { - return - } + const expectedParams: ParamsType = {} + const receivedParams: ParamsType = {} + + if (filter.signer !== undefined) { + expectedParams.signer = filter.signer.toLowerCase() + receivedParams.signer = (await transaction.getSigner()).toLowerCase() } - if (filter?.address !== undefined) { - const address = new PublicKey(filter.address) - const isProgram = data.transaction.message.instructions.find((instruction) => { - return instruction.programId.equals(address) - }) + if (filter.address !== undefined) { + expectedParams.address = filter.address.toLowerCase() + receivedParams.address = (await transaction.getAddress()).toLowerCase() + } - if (isProgram === undefined) { - return - } + if (!objectsEqual(expectedParams, receivedParams)) { + return } this.trigger(transaction) @@ -266,19 +265,8 @@ export class TransactionListener coinProcess(): void { const filter = this.filter as DynamicTransactionListenerFilterType - if ( - filter.signer !== undefined && - filter.sender !== undefined && - filter.signer !== filter.sender - ) { - throw new Error( - 'Sender and signer must be the same in coin transactions. Or only one of them can be defined.' - ) - } - - const sender = filter.sender ?? filter.signer const parameter = new PublicKey( - sender ?? filter.receiver ?? SystemProgram.programId.toBase58() + filter.signer ?? filter.sender ?? filter.receiver ?? SystemProgram.programId.toBase58() ) const callback = async (logs: Logs): Promise => { @@ -294,31 +282,37 @@ export class TransactionListener return } - if (sender !== undefined) { - const isSender = data.transaction.message.accountKeys.find((account) => { - return account.signer && account.pubkey.equals(new PublicKey(sender)) - }) + interface ParamsType { + signer?: string + sender?: string + receiver?: string + amount?: number + } + + const expectedParams: ParamsType = {} + const receivedParams: ParamsType = {} - if (isSender === undefined) { - return - } + if (filter.signer !== undefined) { + expectedParams.signer = filter.signer.toLowerCase() + receivedParams.signer = (await transaction.getSigner()).toLowerCase() + } + + if (filter.sender !== undefined) { + expectedParams.sender = filter.sender.toLowerCase() + receivedParams.sender = (await transaction.getSender()).toLowerCase() } if (filter.receiver !== undefined) { - const receiver = new PublicKey(filter.receiver) - const isReceiver = data.transaction.message.accountKeys.find((account) => { - return account.pubkey.equals(receiver) - }) + expectedParams.receiver = filter.receiver.toLowerCase() + receivedParams.receiver = (await transaction.getReceiver()).toLowerCase() + } - if (isReceiver === undefined) { - return - } + if (filter.amount !== undefined) { + expectedParams.amount = filter.amount + receivedParams.amount = await transaction.getAmount() } - if ( - filter.amount !== undefined && - (await transaction.getAmount()) !== filter.amount - ) { + if (!objectsEqual(expectedParams, receivedParams)) { return } From ec569218b2d854345f6e30267d051c55076e4708 Mon Sep 17 00:00:00 2001 From: Halil Beycan <50718965+BeycanDeveloper@users.noreply.github.com> Date: Mon, 20 May 2024 16:44:31 +0800 Subject: [PATCH 55/90] added mint address catcher --- .../networks/solana/src/models/ContractTransaction.ts | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/packages/networks/solana/src/models/ContractTransaction.ts b/packages/networks/solana/src/models/ContractTransaction.ts index 3a11320..0877d1d 100644 --- a/packages/networks/solana/src/models/ContractTransaction.ts +++ b/packages/networks/solana/src/models/ContractTransaction.ts @@ -20,6 +20,12 @@ export class ContractTransaction extends Transaction implements ContractTransact return '' } - return this.findTransferInstruction(data).programId.toBase58() + const instruction = this.findTransferInstruction(data) + + if (instruction.parsed?.info?.mint !== undefined) { + return instruction.parsed.info.mint + } + + return instruction.programId.toBase58() } } From 085bf194ea502ab2b776a7fcb886835358e99656 Mon Sep 17 00:00:00 2001 From: Halil Beycan <50718965+BeycanDeveloper@users.noreply.github.com> Date: Mon, 20 May 2024 17:05:16 +0800 Subject: [PATCH 56/90] getting spl token mint address for nft and token --- .../solana/src/models/ContractTransaction.ts | 8 +----- .../solana/src/models/NftTransaction.ts | 26 +++++++++++++++++++ .../solana/src/models/TokenTransaction.ts | 26 +++++++++++++++++++ 3 files changed, 53 insertions(+), 7 deletions(-) diff --git a/packages/networks/solana/src/models/ContractTransaction.ts b/packages/networks/solana/src/models/ContractTransaction.ts index 0877d1d..3a11320 100644 --- a/packages/networks/solana/src/models/ContractTransaction.ts +++ b/packages/networks/solana/src/models/ContractTransaction.ts @@ -20,12 +20,6 @@ export class ContractTransaction extends Transaction implements ContractTransact return '' } - const instruction = this.findTransferInstruction(data) - - if (instruction.parsed?.info?.mint !== undefined) { - return instruction.parsed.info.mint - } - - return instruction.programId.toBase58() + return this.findTransferInstruction(data).programId.toBase58() } } diff --git a/packages/networks/solana/src/models/NftTransaction.ts b/packages/networks/solana/src/models/NftTransaction.ts index 6183602..9c0e01a 100644 --- a/packages/networks/solana/src/models/NftTransaction.ts +++ b/packages/networks/solana/src/models/NftTransaction.ts @@ -17,6 +17,32 @@ export class NftTransaction extends ContractTransaction implements NftTransactio }) as ParsedInstruction } + /** + * @returns {Promise} Contract address of the transaction + */ + async getAddress(): Promise { + const data = await this.getData() + if (data === null) { + return '' + } + + const instruction = this.findTransferInstruction(data) + + if (instruction.parsed?.info.mint !== undefined) { + return instruction.parsed.info.mint + } + + const postBalance = data.meta?.postTokenBalances?.find((balance: any): boolean => { + return balance.mint !== undefined + }) + + if (postBalance !== undefined) { + return postBalance.mint + } + + return await super.getAddress() + } + /** * @returns {Promise} Receiver wallet address */ diff --git a/packages/networks/solana/src/models/TokenTransaction.ts b/packages/networks/solana/src/models/TokenTransaction.ts index 18142cf..b377f15 100644 --- a/packages/networks/solana/src/models/TokenTransaction.ts +++ b/packages/networks/solana/src/models/TokenTransaction.ts @@ -17,6 +17,32 @@ export class TokenTransaction extends ContractTransaction implements TokenTransa }) as ParsedInstruction } + /** + * @returns {Promise} Contract address of the transaction + */ + async getAddress(): Promise { + const data = await this.getData() + if (data === null) { + return '' + } + + const instruction = this.findTransferInstruction(data) + + if (instruction.parsed?.info.mint !== undefined) { + return instruction.parsed.info.mint + } + + const postBalance = data.meta?.postTokenBalances?.find((balance: any): boolean => { + return balance.mint !== undefined + }) + + if (postBalance !== undefined) { + return postBalance.mint + } + + return await super.getAddress() + } + /** * @returns {Promise} Wallet address of the receiver of transaction */ From 9b6ab22394009b270ae927714607e17437b80a28 Mon Sep 17 00:00:00 2001 From: Halil Beycan <50718965+BeycanDeveloper@users.noreply.github.com> Date: Mon, 20 May 2024 19:26:48 +0800 Subject: [PATCH 57/90] nft and token completed --- .../solana/src/models/ContractTransaction.ts | 4 +- .../solana/src/models/NftTransaction.ts | 24 ++- .../solana/src/models/TokenTransaction.ts | 55 +++-- .../src/services/TransactionListener.ts | 197 +++++++++++++++++- 4 files changed, 236 insertions(+), 44 deletions(-) diff --git a/packages/networks/solana/src/models/ContractTransaction.ts b/packages/networks/solana/src/models/ContractTransaction.ts index 3a11320..4fd88e2 100644 --- a/packages/networks/solana/src/models/ContractTransaction.ts +++ b/packages/networks/solana/src/models/ContractTransaction.ts @@ -6,7 +6,7 @@ export class ContractTransaction extends Transaction implements ContractTransact /** * @returns {Promise} Wallet address of the receiver of transaction */ - findTransferInstruction(data: any): ParsedInstruction { + findTransferInstruction(data: any): ParsedInstruction | null { const length = data.transaction.message.instructions.length return data.transaction.message.instructions[length - 1] as ParsedInstruction } @@ -20,6 +20,6 @@ export class ContractTransaction extends Transaction implements ContractTransact return '' } - return this.findTransferInstruction(data).programId.toBase58() + return this.findTransferInstruction(data)?.programId.toBase58() ?? '' } } diff --git a/packages/networks/solana/src/models/NftTransaction.ts b/packages/networks/solana/src/models/NftTransaction.ts index 9c0e01a..31de29f 100644 --- a/packages/networks/solana/src/models/NftTransaction.ts +++ b/packages/networks/solana/src/models/NftTransaction.ts @@ -7,14 +7,16 @@ export class NftTransaction extends ContractTransaction implements NftTransactio /** * @returns {Promise} Wallet address of the receiver of transaction */ - findTransferInstruction(data: any): ParsedInstruction { - return data.transaction.message.instructions.find((instruction: any): boolean => { - return ( - instruction.parsed !== undefined && - (instruction.parsed.type === 'transferChecked' || - instruction.parsed.type === 'transfer') - ) - }) as ParsedInstruction + findTransferInstruction(data: any): ParsedInstruction | null { + return ( + (data.transaction.message.instructions.find((instruction: any): boolean => { + return ( + instruction.parsed !== undefined && + (instruction.parsed.type === 'transferChecked' || + instruction.parsed.type === 'transfer') + ) + }) as ParsedInstruction) ?? null + ) } /** @@ -28,7 +30,7 @@ export class NftTransaction extends ContractTransaction implements NftTransactio const instruction = this.findTransferInstruction(data) - if (instruction.parsed?.info.mint !== undefined) { + if (instruction?.parsed?.info.mint !== undefined) { return instruction.parsed.info.mint } @@ -69,7 +71,7 @@ export class NftTransaction extends ContractTransaction implements NftTransactio return '' } - return this.findTransferInstruction(data).parsed.info.authority + return this.findTransferInstruction(data)?.parsed.info.authority } /** @@ -82,7 +84,7 @@ export class NftTransaction extends ContractTransaction implements NftTransactio return '' } - return this.findTransferInstruction(data).parsed.info.mint + return this.findTransferInstruction(data)?.parsed.info.mint } /** diff --git a/packages/networks/solana/src/models/TokenTransaction.ts b/packages/networks/solana/src/models/TokenTransaction.ts index b377f15..d748020 100644 --- a/packages/networks/solana/src/models/TokenTransaction.ts +++ b/packages/networks/solana/src/models/TokenTransaction.ts @@ -1,20 +1,24 @@ -import type { ParsedInstruction } from '@solana/web3.js' +import { PublicKey } from '@solana/web3.js' +import { math } from '@multiplechain/utils' import { TransactionStatusEnum } from '@multiplechain/types' import { ContractTransaction } from './ContractTransaction.ts' +import type { ParsedAccountData, ParsedInstruction } from '@solana/web3.js' import { AssetDirectionEnum, type TokenTransactionInterface } from '@multiplechain/types' export class TokenTransaction extends ContractTransaction implements TokenTransactionInterface { /** * @returns {Promise} Wallet address of the receiver of transaction */ - findTransferInstruction(data: any): ParsedInstruction { - return data.transaction.message.instructions.find((instruction: any): boolean => { - return ( - instruction.parsed !== undefined && - (instruction.parsed.type === 'transferChecked' || - instruction.parsed.type === 'transfer') - ) - }) as ParsedInstruction + findTransferInstruction(data: any): ParsedInstruction | null { + return ( + (data.transaction.message.instructions.find((instruction: any): boolean => { + return ( + instruction.parsed !== undefined && + (instruction.parsed.type === 'transferChecked' || + instruction.parsed.type === 'transfer') + ) + }) as ParsedInstruction) ?? null + ) } /** @@ -28,7 +32,7 @@ export class TokenTransaction extends ContractTransaction implements TokenTransa const instruction = this.findTransferInstruction(data) - if (instruction.parsed?.info.mint !== undefined) { + if (instruction?.parsed?.info.mint !== undefined) { return instruction.parsed.info.mint } @@ -52,11 +56,12 @@ export class TokenTransaction extends ContractTransaction implements TokenTransa return '' } - if (data.meta?.postTokenBalances?.length === undefined) { - return '' - } + const instruction = this.findTransferInstruction(data) + const accountInfo = await this.provider.web3.getParsedAccountInfo( + new PublicKey(instruction?.parsed.info.destination as string) + ) - return data.meta.postTokenBalances[1].owner ?? '' + return (accountInfo.value?.data as ParsedAccountData)?.parsed?.info?.owner ?? '' } /** @@ -68,11 +73,7 @@ export class TokenTransaction extends ContractTransaction implements TokenTransa return '' } - if (data.meta?.postTokenBalances?.length === undefined) { - return '' - } - - return data.meta.postTokenBalances[0].owner ?? '' + return this.findTransferInstruction(data)?.parsed.info.authority } /** @@ -84,7 +85,21 @@ export class TokenTransaction extends ContractTransaction implements TokenTransa return 0 } - return this.findTransferInstruction(data).parsed.info.tokenAmount.uiAmount as number + const instruction = this.findTransferInstruction(data) + + if (instruction?.parsed?.info?.tokenAmount?.uiAmount !== undefined) { + return instruction.parsed.info.tokenAmount.uiAmount as number + } + + const amount = instruction?.parsed.info.amount as number + + const postBalance = data.meta?.postTokenBalances?.find((balance: any): boolean => { + return balance.mint !== undefined + }) + + const decimals = postBalance?.uiTokenAmount?.decimals ?? 0 + + return math.div(amount, math.pow(10, decimals), decimals) } /** diff --git a/packages/networks/solana/src/services/TransactionListener.ts b/packages/networks/solana/src/services/TransactionListener.ts index eaddab2..3643d46 100644 --- a/packages/networks/solana/src/services/TransactionListener.ts +++ b/packages/networks/solana/src/services/TransactionListener.ts @@ -1,5 +1,4 @@ import type { - TransactionTypeEnum, DynamicTransactionType, TransactionListenerInterface, TransactionListenerCallbackType, @@ -12,13 +11,18 @@ import { PublicKey, SystemProgram, type Logs, + type LogsFilter, + type ParsedAccountData, type ParsedInstruction, type PartiallyDecodedInstruction } from '@solana/web3.js' -import { TransactionListenerProcessIndex } from '@multiplechain/types' -import { ContractTransaction } from '../models/ContractTransaction.ts' -import { CoinTransaction } from '../models/CoinTransaction.ts' import { objectsEqual } from '@multiplechain/utils' +import { NftTransaction } from '../models/NftTransaction.ts' +import { CoinTransaction } from '../models/CoinTransaction.ts' +import { TokenTransaction } from '../models/TokenTransaction.ts' +import { ContractTransaction } from '../models/ContractTransaction.ts' +import { TransactionListenerProcessIndex, TransactionTypeEnum } from '@multiplechain/types' +import { getAssociatedTokenAddressSync } from '@solana/spl-token' export class TransactionListener implements TransactionListenerInterface @@ -250,7 +254,8 @@ export class TransactionListener } } - const parameter = filter.signer === undefined ? 'all' : new PublicKey(filter.signer) + const address = filter.signer ?? filter.address + const parameter = address !== undefined ? new PublicKey(address) : 'all' const subscriptionId = this.provider.web3.onLogs(parameter, callback, 'confirmed') this.dynamicStop = () => { @@ -329,19 +334,189 @@ export class TransactionListener } } + private async tokenNftCondition( + _transaction: TokenTransaction | NftTransaction + ): Promise { + const filter = + this.type === TransactionTypeEnum.TOKEN + ? (this.filter as DynamicTransactionListenerFilterType) + : (this.filter as DynamicTransactionListenerFilterType) + + const transaction = + this.type === TransactionTypeEnum.TOKEN + ? (_transaction as TokenTransaction) + : (_transaction as NftTransaction) + + interface ParamsType { + signer?: string + sender?: string + receiver?: string + address?: string + amount?: number + nftId?: number | string + } + + const expectedParams: ParamsType = {} + const receivedParams: ParamsType = {} + + if (filter.signer !== undefined) { + expectedParams.signer = filter.signer.toLowerCase() + receivedParams.signer = (await transaction.getSigner()).toLowerCase() + } + + if (filter.sender !== undefined) { + expectedParams.sender = filter.sender.toLowerCase() + receivedParams.sender = (await transaction.getSender()).toLowerCase() + } + + if (filter.receiver !== undefined) { + expectedParams.receiver = filter.receiver.toLowerCase() + receivedParams.receiver = (await transaction.getReceiver()).toLowerCase() + } + + if (filter.address !== undefined) { + expectedParams.address = filter.address.toLowerCase() + receivedParams.address = (await transaction.getAddress()).toLowerCase() + } + + if (this.type === TransactionTypeEnum.TOKEN) { + const tFilter = + filter as DynamicTransactionListenerFilterType + const tTransaction = _transaction as TokenTransaction + if (tFilter.amount !== undefined) { + expectedParams.amount = tFilter.amount + receivedParams.amount = await tTransaction.getAmount() + } + } else { + const nFilter = filter as DynamicTransactionListenerFilterType + const nTransaction = _transaction as NftTransaction + if (nFilter.nftId !== undefined) { + expectedParams.nftId = nFilter.nftId + receivedParams.nftId = await nTransaction.getNftId() + } + } + + return objectsEqual(expectedParams, receivedParams) + } + + private async createTokenNftListenParameter(): Promise { + const filter = + this.type === TransactionTypeEnum.TOKEN + ? (this.filter as DynamicTransactionListenerFilterType) + : (this.filter as DynamicTransactionListenerFilterType) + + let parameter: LogsFilter = 'all' + + if (filter?.address !== undefined) { + const tokenMintAddress = new PublicKey(filter.address) + const accountInfo = await this.provider.web3.getParsedAccountInfo(tokenMintAddress) + + const result = accountInfo?.value + const data = (result?.data as ParsedAccountData) ?? null + const programId = ['spl-token', 'spl-token-2022'].includes(data?.program) + ? result?.owner + : null + + parameter = programId ?? tokenMintAddress ?? 'all' + const address = filter.sender ?? filter.receiver + + if (programId !== null && address !== undefined) { + const addressPubKey = new PublicKey(address) + const ownerAccount = getAssociatedTokenAddressSync( + tokenMintAddress, + addressPubKey, + false, + programId + ) + + parameter = ownerAccount + } + } + + return parameter + } + /** * Token transaction process - * @returns {void} + * @returns {Promise} */ - tokenProcess(): void { - // Token transaction process + async tokenProcess(): Promise { + const callback = async (logs: Logs): Promise => { + try { + const transaction = new TokenTransaction(logs.signature) + const data = await transaction.getData() + + if (data === null) { + return + } + + if (this.isSystemProgram(data.transaction.message.instructions)) { + return + } + + const instruction = transaction.findTransferInstruction(data) + + if (instruction === null || instruction.parsed?.info?.tokenAmount?.decimals === 0) { + return + } + + if (!(await this.tokenNftCondition(transaction))) { + return + } + + this.trigger(transaction) + } catch (error) { + // Maybe in future, we can add logging system + } + } + + const parameter = await this.createTokenNftListenParameter() + const subscriptionId = this.provider.web3.onLogs(parameter, callback, 'confirmed') + + this.dynamicStop = () => { + void this.provider.web3.removeOnLogsListener(subscriptionId) + } } /** * NFT transaction process - * @returns {void} + * @returns {Promise} */ - nftProcess(): void { - // NFT transaction process + async nftProcess(): Promise { + const callback = async (logs: Logs): Promise => { + try { + const transaction = new NftTransaction(logs.signature) + const data = await transaction.getData() + + if (data === null) { + return + } + + if (this.isSystemProgram(data.transaction.message.instructions)) { + return + } + + const instruction = transaction.findTransferInstruction(data) + + if (instruction === null || instruction.parsed?.info?.tokenAmount?.decimals !== 0) { + return + } + + if (!(await this.tokenNftCondition(transaction))) { + return + } + + this.trigger(transaction) + } catch (error) { + // Maybe in future, we can add logging system + } + } + + const parameter = await this.createTokenNftListenParameter() + const subscriptionId = this.provider.web3.onLogs(parameter, callback, 'confirmed') + + this.dynamicStop = () => { + void this.provider.web3.removeOnLogsListener(subscriptionId) + } } } From 02ed2b2f75bb41bcd89f6bef46e24d20f7152887 Mon Sep 17 00:00:00 2001 From: Halil Beycan <50718965+BeycanDeveloper@users.noreply.github.com> Date: Mon, 20 May 2024 19:30:51 +0800 Subject: [PATCH 58/90] updated --- packages/networks/solana/tests/models.spec.ts | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/packages/networks/solana/tests/models.spec.ts b/packages/networks/solana/tests/models.spec.ts index 62c3985..7c47351 100644 --- a/packages/networks/solana/tests/models.spec.ts +++ b/packages/networks/solana/tests/models.spec.ts @@ -19,6 +19,9 @@ const nftTransferTx = String(process.env.SOL_NFT_TRANSFER_TX) const sender = String(process.env.SOL_MODEL_TEST_SENDER) const receiver = String(process.env.SOL_MODEL_TEST_RECEIVER) +const tokenTestAddress = String(process.env.SOL_TOKEN_TEST_ADDRESS) +const token2022TestAddress = String(process.env.SOL_TOKEN_2022_TEST_ADDRESS) + describe('Transaction', () => { const tx = new Transaction(solTransferTx) it('Id', async () => { @@ -115,9 +118,7 @@ describe('Token Transaction', () => { }) it('Program', async () => { - expect((await tx.getAddress()).toLowerCase()).toBe( - 'TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA'.toLowerCase() - ) + expect((await tx.getAddress()).toLowerCase()).toBe(tokenTestAddress.toLowerCase()) }) it('Amount', async () => { @@ -147,9 +148,7 @@ describe('Token Transaction', () => { }) it('Program', async () => { - expect((await tx2022.getAddress()).toLowerCase()).toBe( - 'TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb'.toLowerCase() - ) + expect((await tx2022.getAddress()).toLowerCase()).toBe(token2022TestAddress.toLowerCase()) }) it('Amount', async () => { @@ -183,9 +182,7 @@ describe('NFT Transaction', () => { }) it('Program', async () => { - expect((await tx.getAddress()).toLowerCase()).toBe( - 'TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA'.toLowerCase() - ) + expect((await tx.getAddress()).toLowerCase()).toBe(nftId.toLowerCase()) }) it('Sender', async () => { From 4e68be16df4c70dbd79448043728ac829a46a41d Mon Sep 17 00:00:00 2001 From: Halil Beycan <50718965+BeycanDeveloper@users.noreply.github.com> Date: Mon, 20 May 2024 19:46:47 +0800 Subject: [PATCH 59/90] updated for data verify --- packages/networks/solana/src/models/Transaction.ts | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/packages/networks/solana/src/models/Transaction.ts b/packages/networks/solana/src/models/Transaction.ts index 061d01c..6daa7cd 100644 --- a/packages/networks/solana/src/models/Transaction.ts +++ b/packages/networks/solana/src/models/Transaction.ts @@ -59,11 +59,14 @@ export class Transaction implements TransactionInterface { let status = await this.getStatus() if (status === TransactionStatusEnum.PENDING) { const latestBlockHash = await this.provider.web3.getLatestBlockhash() - await this.provider.web3.confirmTransaction({ - signature: this.id, - blockhash: latestBlockHash.blockhash, - lastValidBlockHeight: latestBlockHash.lastValidBlockHeight - }) + await this.provider.web3.confirmTransaction( + { + signature: this.id, + blockhash: latestBlockHash.blockhash, + lastValidBlockHeight: latestBlockHash.lastValidBlockHeight + }, + 'finalized' + ) status = await this.getStatus() } if (status === TransactionStatusEnum.CONFIRMED) { From fd1bbb37284c977ed5391b3d9085660092d44edc Mon Sep 17 00:00:00 2001 From: Halil Beycan <50718965+BeycanDeveloper@users.noreply.github.com> Date: Mon, 20 May 2024 22:20:23 +0800 Subject: [PATCH 60/90] listener tests updated --- .env.example | 5 +- .../networks/bitcoin/tests/services.spec.ts | 23 +- .../evm-chains/tests/services.spec.ts | 131 +++++++----- .../networks/solana/tests/services.spec.ts | 197 ++++++++++++++++++ vitest.config.ts | 5 + 5 files changed, 302 insertions(+), 59 deletions(-) diff --git a/.env.example b/.env.example index f127fe9..799d0b8 100644 --- a/.env.example +++ b/.env.example @@ -13,7 +13,7 @@ EVM_TRANSACTION_LISTENER_TEST_IS_ACTIVE=false EVM_COIN_BALANCE_TEST_AMOUNT=0.01 EVM_TOKEN_BALANCE_TEST_AMOUNT=1000 EVM_NFT_BALANCE_TEST_AMOUNT=2 -EVM_TRANSFER_TEST_AMOUNT=0.0001 +EVM_TRANSFER_TEST_AMOUNT=0.01 EVM_TOKEN_TRANSFER_TEST_AMOUNT=1 EVM_TOKEN_APPROVE_TEST_AMOUNT=100 EVM_NFT_TRANSFER_ID=7 @@ -111,7 +111,8 @@ SOL_TOKEN_TRANSFER_TEST_AMOUNT=1 SOL_TOKEN_APPROVE_TEST_AMOUNT=10 #NFT ID SOL_NFT_TRANSFER_ID='FxN19KB5UeZJFwxLFgT57WvYYXYhBFKxVumfq37xU4Ck' - +SOL_NFT_TRANSFER_ID2='EBQjkpi6VdY3WF9ihi1sVhjkNDjfCorg1LJGd3Vnn9Ec' +SOL_TOKEN_PROGRAM='TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA' SOL_BALANCE_TEST_ADDRESS='2i6NifwwBGJKUEhYhqbGwu66kDhbfyjgp7zPN5dQsKsE' SOL_SENDER_PRIVATE_KEY='2hh51RHd1cEgiuEj2azZJFNphh27S8578otEHw8WvUia1yEBaW7o7XNuxdV1qQYbvxL5FHrcHpbZMCCxULTkCHRq' SOL_RECEIVER_PRIVATE_KEY='57XnG9wtVMVV5BZnZbmaN3JTQ7Mzkmbyh4ooMC45YypJz3gF16nGfCJw3hWGQjLFbKmruaF3N3BH3fJAGD6stGCb' diff --git a/packages/networks/bitcoin/tests/services.spec.ts b/packages/networks/bitcoin/tests/services.spec.ts index e01ff25..d5e59cb 100644 --- a/packages/networks/bitcoin/tests/services.spec.ts +++ b/packages/networks/bitcoin/tests/services.spec.ts @@ -6,6 +6,7 @@ import { TransactionListener } from '../src/services/TransactionListener.ts' import { TransactionTypeEnum } from '@multiplechain/types' import { CoinTransaction } from '../src/models/CoinTransaction.ts' import { Coin } from '../src/assets/Coin.ts' +import { sleep } from '@multiplechain/utils' const senderTestAddress = String(process.env.BTC_SENDER_ADDRESS) const receiverTestAddress = String(process.env.BTC_RECEIVER_ADDRESS) @@ -44,15 +45,23 @@ describe('Transaction Listener', () => { receiver: receiverTestAddress }) - void listener.on((transaction) => { - listener.stop() - expect(transaction).toBeInstanceOf(CoinTransaction) - }) - const signer = await new Coin().transfer(senderTestAddress, receiverTestAddress, 0.0001) - const transaction = await (await signer.sign(senderPrivateKey)).send() + const waitListenerEvent = async (): Promise => { + return await new Promise((resolve, reject) => { + void listener + .on((transaction) => { + listener.stop() + resolve(transaction) + }) + .then(async () => { + await sleep(2000) + void (await signer.sign(senderPrivateKey)).send() + }) + .catch(reject) + }) + } - expect(transaction).toBeInstanceOf(CoinTransaction) + expect(await waitListenerEvent()).toBeInstanceOf(CoinTransaction) }) }) diff --git a/packages/networks/evm-chains/tests/services.spec.ts b/packages/networks/evm-chains/tests/services.spec.ts index 0b848cb..1b9e63e 100644 --- a/packages/networks/evm-chains/tests/services.spec.ts +++ b/packages/networks/evm-chains/tests/services.spec.ts @@ -148,18 +148,24 @@ describe('Transaction Listener', () => { signer: senderTestAddress }) - void listener.on((transaction) => { - listener.stop() - expect(transaction).toBeInstanceOf(Transaction) - }) - const signer = await new Coin().transfer(senderTestAddress, receiverTestAddress, 0.0001) - const transaction = await (await signer.sign(senderPrivateKey)).send() - - expect(transaction).toBeInstanceOf(Transaction) - - void (await transaction.wait()) + const waitListenerEvent = async (): Promise => { + return await new Promise((resolve, reject) => { + void listener + .on((transaction) => { + listener.stop() + resolve(transaction) + }) + .then(async () => { + await waitSecondsBeforeThanNewTx(2) + void (await signer.sign(senderPrivateKey)).send() + }) + .catch(reject) + }) + } + + expect(await waitListenerEvent()).toBeInstanceOf(Transaction) }) it('Contract', async () => { @@ -170,22 +176,28 @@ describe('Transaction Listener', () => { address: tokenTestAddress }) - void listener.on((transaction) => { - listener.stop() - expect(transaction).toBeInstanceOf(ContractTransaction) - }) - const signer = await new Token(tokenTestAddress).transfer( senderTestAddress, receiverTestAddress, 0.01 ) - const transaction = await (await signer.sign(senderPrivateKey)).send() - - expect(transaction).toBeInstanceOf(ContractTransaction) - - void (await transaction.wait()) + const waitListenerEvent = async (): Promise => { + return await new Promise((resolve, reject) => { + void listener + .on((transaction) => { + listener.stop() + resolve(transaction) + }) + .then(async () => { + await waitSecondsBeforeThanNewTx(2) + void (await signer.sign(senderPrivateKey)).send() + }) + .catch(reject) + }) + } + + expect(await waitListenerEvent()).toBeInstanceOf(ContractTransaction) }) it('Coin', async () => { @@ -196,18 +208,24 @@ describe('Transaction Listener', () => { receiver: receiverTestAddress }) - void listener.on((transaction) => { - listener.stop() - expect(transaction).toBeInstanceOf(CoinTransaction) - }) - const signer = await new Coin().transfer(senderTestAddress, receiverTestAddress, 0.0001) - const transaction = await (await signer.sign(senderPrivateKey)).send() - - expect(transaction).toBeInstanceOf(CoinTransaction) - - void (await transaction.wait()) + const waitListenerEvent = async (): Promise => { + return await new Promise((resolve, reject) => { + void listener + .on((transaction) => { + listener.stop() + resolve(transaction) + }) + .then(async () => { + await waitSecondsBeforeThanNewTx(2) + void (await signer.sign(senderPrivateKey)).send() + }) + .catch(reject) + }) + } + + expect(await waitListenerEvent()).toBeInstanceOf(CoinTransaction) }) it('Token', async () => { @@ -219,22 +237,28 @@ describe('Transaction Listener', () => { address: tokenTestAddress }) - void listener.on((transaction) => { - listener.stop() - expect(transaction).toBeInstanceOf(TokenTransaction) - }) - const signer = await new Token(tokenTestAddress).transfer( senderTestAddress, receiverTestAddress, 0.01 ) - const transaction = await (await signer.sign(senderPrivateKey)).send() - - expect(transaction).toBeInstanceOf(TokenTransaction) - - void (await transaction.wait()) + const waitListenerEvent = async (): Promise => { + return await new Promise((resolve, reject) => { + void listener + .on((transaction) => { + listener.stop() + resolve(transaction) + }) + .then(async () => { + await waitSecondsBeforeThanNewTx(2) + void (await signer.sign(senderPrivateKey)).send() + }) + .catch(reject) + }) + } + + expect(await waitListenerEvent()).toBeInstanceOf(TokenTransaction) }) it('NFT', async () => { @@ -246,20 +270,27 @@ describe('Transaction Listener', () => { address: nftTestAddress }) - void listener.on((transaction) => { - listener.stop() - expect(transaction).toBeInstanceOf(NftTransaction) - }) - const nft = new NFT(nftTestAddress) const signer = await nft.transfer(senderTestAddress, receiverTestAddress, 9) - const transaction = await (await signer.sign(senderPrivateKey)).send() - + const waitListenerEvent = async (): Promise => { + return await new Promise((resolve, reject) => { + void listener + .on((transaction) => { + listener.stop() + resolve(transaction) + }) + .then(async () => { + await waitSecondsBeforeThanNewTx(2) + void (await signer.sign(senderPrivateKey)).send() + }) + .catch(reject) + }) + } + + const transaction = await waitListenerEvent() expect(transaction).toBeInstanceOf(NftTransaction) - - void (await transaction.wait()) - + await transaction.wait() await waitSecondsBeforeThanNewTx(10) const newSigner = await nft.transfer(receiverTestAddress, senderTestAddress, 9) diff --git a/packages/networks/solana/tests/services.spec.ts b/packages/networks/solana/tests/services.spec.ts index 37d09f4..ae03245 100644 --- a/packages/networks/solana/tests/services.spec.ts +++ b/packages/networks/solana/tests/services.spec.ts @@ -3,6 +3,35 @@ import { describe, it, expect } from 'vitest' import { provider } from './setup.ts' import { Provider } from '../src/services/Provider.ts' +import { NFT } from '../src/assets/NFT.ts' +import { Coin } from '../src/assets/Coin.ts' +import { Token } from '../src/assets/Token.ts' +import { sleep } from '@multiplechain/utils' +import { TransactionTypeEnum } from '@multiplechain/types' +import { Transaction } from '../src/models/Transaction.ts' +import { NftTransaction } from '../src/models/NftTransaction.ts' +import { CoinTransaction } from '../src/models/CoinTransaction.ts' +import { TokenTransaction } from '../src/models/TokenTransaction.ts' +import { ContractTransaction } from '../src/models/ContractTransaction.ts' +import { TransactionListener } from '../src/services/TransactionListener.ts' + +const senderPrivateKey = String(process.env.SOL_SENDER_PRIVATE_KEY) +const receiverPrivateKey = String(process.env.SOL_RECEIVER_PRIVATE_KEY) +const senderTestAddress = String(process.env.SOL_SENDER_TEST_ADDRESS) +const receiverTestAddress = String(process.env.SOL_RECEIVER_TEST_ADDRESS) +const tokenTestAddress = String(process.env.SOL_TOKEN_TEST_ADDRESS) +const tokenProgram = String(process.env.SOL_TOKEN_PROGRAM) +const nftTestAddress = String(process.env.SOL_NFT_TEST_ADDRESS) +const nftTestAddress2 = String(process.env.SOL_NFT_TRANSFER_ID2) + +const transactionListenerTestIsActive = Boolean( + process.env.SOL_TRANSACTION_LISTENER_TEST_IS_ACTIVE !== 'false' +) + +const waitSecondsBeforeThanNewTx = async (seconds: number): Promise => { + return await new Promise((resolve) => setTimeout(resolve, seconds * 1000)) +} + describe('Provider', () => { it('isTestnet', () => { expect(provider.isTestnet()).toBe(true) @@ -20,3 +49,171 @@ describe('Provider', () => { expect(await provider.checkWsConnection()).toBe(true) }) }) + +describe('Transaction Listener', () => { + if (!transactionListenerTestIsActive) { + it('No test is active', () => { + expect(true).toBe(true) + }) + return + } + + it('General', async () => { + const listener = new TransactionListener(TransactionTypeEnum.GENERAL, { + signer: senderTestAddress + }) + + const signer = await new Coin().transfer(senderTestAddress, receiverTestAddress, 0.0001) + + const waitListenerEvent = async (): Promise => { + return await new Promise((resolve, reject) => { + void listener + .on((transaction) => { + listener.stop() + resolve(transaction) + }) + .then(async () => { + await sleep(2000) + await (await signer.sign(senderPrivateKey)).send() + }) + .catch(reject) + }) + } + + expect(await waitListenerEvent()).toBeInstanceOf(Transaction) + }) + + it('Contract', async () => { + await waitSecondsBeforeThanNewTx(10) + + const listener = new TransactionListener(TransactionTypeEnum.CONTRACT, { + signer: senderTestAddress, + address: tokenProgram + }) + + const signer = await new Token(tokenTestAddress).transfer( + senderTestAddress, + receiverTestAddress, + 0.01 + ) + + const waitListenerEvent = async (): Promise => { + return await new Promise((resolve, reject) => { + void listener + .on((transaction) => { + listener.stop() + resolve(transaction) + }) + .then(async () => { + await sleep(2000) + await (await signer.sign(senderPrivateKey)).send() + }) + .catch(reject) + }) + } + + expect(await waitListenerEvent()).toBeInstanceOf(ContractTransaction) + }) + + it('Coin', async () => { + await waitSecondsBeforeThanNewTx(10) + + const listener = new TransactionListener(TransactionTypeEnum.COIN, { + signer: senderTestAddress, + receiver: receiverTestAddress + }) + + const signer = await new Coin().transfer(senderTestAddress, receiverTestAddress, 0.0001) + + const waitListenerEvent = async (): Promise => { + return await new Promise((resolve, reject) => { + void listener + .on((transaction) => { + listener.stop() + resolve(transaction) + }) + .then(async () => { + await sleep(2000) + await (await signer.sign(senderPrivateKey)).send() + }) + .catch(reject) + }) + } + + expect(await waitListenerEvent()).toBeInstanceOf(CoinTransaction) + }) + + it('Token', async () => { + await waitSecondsBeforeThanNewTx(10) + + const listener = new TransactionListener(TransactionTypeEnum.TOKEN, { + signer: senderTestAddress, + receiver: receiverTestAddress, + address: tokenTestAddress + }) + + const signer = await new Token(tokenTestAddress).transfer( + senderTestAddress, + receiverTestAddress, + 0.01 + ) + + const waitListenerEvent = async (): Promise => { + return await new Promise((resolve, reject) => { + void listener + .on((transaction) => { + listener.stop() + resolve(transaction) + }) + .then(async () => { + await sleep(2000) + await (await signer.sign(senderPrivateKey)).send() + }) + .catch(reject) + }) + } + + expect(await waitListenerEvent()).toBeInstanceOf(TokenTransaction) + }) + + it('NFT', async () => { + await waitSecondsBeforeThanNewTx(10) + + const listener = new TransactionListener(TransactionTypeEnum.NFT, { + signer: senderTestAddress, + receiver: receiverTestAddress, + address: nftTestAddress2 + }) + + const nft = new NFT(nftTestAddress) + const signer = await nft.transfer(senderTestAddress, receiverTestAddress, nftTestAddress2) + + const waitListenerEvent = async (): Promise => { + return await new Promise((resolve, reject) => { + void listener + .on((transaction) => { + listener.stop() + resolve(transaction) + }) + .then(async () => { + await sleep(2000) + await (await signer.sign(senderPrivateKey)).send() + }) + .catch(reject) + }) + } + + const transaction = await waitListenerEvent() + expect(transaction).toBeInstanceOf(NftTransaction) + await transaction.wait() + await waitSecondsBeforeThanNewTx(10) + + const newSigner = await nft.transfer( + receiverTestAddress, + senderTestAddress, + nftTestAddress2 + ) + + void (await newSigner.sign(receiverPrivateKey)).send() + }) +}) diff --git a/vitest.config.ts b/vitest.config.ts index 98b864d..01ebc40 100644 --- a/vitest.config.ts +++ b/vitest.config.ts @@ -24,6 +24,11 @@ export default mergeConfig( ] }, watch: false, + maxConcurrency: 1, + sequence: { + shuffle: false, + concurrent: false + }, testTimeout: 180000, environment: 'node', exclude: [...configDefaults.exclude, 'e2e/*', '**/boilerplate/**'], From 851376a22c775ec0dd674280c23a73a65636d2f4 Mon Sep 17 00:00:00 2001 From: Halil Beycan <50718965+BeycanDeveloper@users.noreply.github.com> Date: Mon, 20 May 2024 22:33:12 +0800 Subject: [PATCH 61/90] updated --- packages/networks/solana/tests/services.spec.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/networks/solana/tests/services.spec.ts b/packages/networks/solana/tests/services.spec.ts index ae03245..e7aa9f2 100644 --- a/packages/networks/solana/tests/services.spec.ts +++ b/packages/networks/solana/tests/services.spec.ts @@ -74,7 +74,7 @@ describe('Transaction Listener', () => { }) .then(async () => { await sleep(2000) - await (await signer.sign(senderPrivateKey)).send() + void (await signer.sign(senderPrivateKey)).send() }) .catch(reject) }) @@ -106,7 +106,7 @@ describe('Transaction Listener', () => { }) .then(async () => { await sleep(2000) - await (await signer.sign(senderPrivateKey)).send() + void (await signer.sign(senderPrivateKey)).send() }) .catch(reject) }) @@ -134,7 +134,7 @@ describe('Transaction Listener', () => { }) .then(async () => { await sleep(2000) - await (await signer.sign(senderPrivateKey)).send() + void (await signer.sign(senderPrivateKey)).send() }) .catch(reject) }) @@ -167,7 +167,7 @@ describe('Transaction Listener', () => { }) .then(async () => { await sleep(2000) - await (await signer.sign(senderPrivateKey)).send() + void (await signer.sign(senderPrivateKey)).send() }) .catch(reject) }) @@ -197,7 +197,7 @@ describe('Transaction Listener', () => { }) .then(async () => { await sleep(2000) - await (await signer.sign(senderPrivateKey)).send() + void (await signer.sign(senderPrivateKey)).send() }) .catch(reject) }) From faf5f058ff88a82a39f98f9e6be9ce560b818c70 Mon Sep 17 00:00:00 2001 From: Halil Beycan <50718965+BeycanDeveloper@users.noreply.github.com> Date: Tue, 21 May 2024 12:39:30 +0800 Subject: [PATCH 62/90] updated --- packages/networks/boilerplate/src/models/Transaction.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/networks/boilerplate/src/models/Transaction.ts b/packages/networks/boilerplate/src/models/Transaction.ts index 15f111d..bb7c04e 100644 --- a/packages/networks/boilerplate/src/models/Transaction.ts +++ b/packages/networks/boilerplate/src/models/Transaction.ts @@ -30,9 +30,10 @@ export class Transaction implements TransactionInterface { } /** - * @returns {Promise} Wait for the transaction to be confirmed + * @param {number} ms - Milliseconds to wait for the transaction to be confirmed. Default is 4000ms + * @returns {Promise} Status of the transaction */ - async wait(): Promise { + async wait(ms: number = 4000): Promise { return await Promise.resolve(TransactionStatusEnum.CONFIRMED) } From 561e3e42b885fa106ff5f3e526e446773f00881e Mon Sep 17 00:00:00 2001 From: Halil Beycan <50718965+BeycanDeveloper@users.noreply.github.com> Date: Tue, 21 May 2024 12:39:38 +0800 Subject: [PATCH 63/90] created tests --- .../networks/boilerplate/tests/assets.spec.ts | 257 +++++++++++++++++- .../networks/boilerplate/tests/models.spec.ts | 152 ++++++++++- .../boilerplate/tests/services.spec.ts | 219 ++++++++++++++- 3 files changed, 618 insertions(+), 10 deletions(-) diff --git a/packages/networks/boilerplate/tests/assets.spec.ts b/packages/networks/boilerplate/tests/assets.spec.ts index 34c5579..1902a05 100644 --- a/packages/networks/boilerplate/tests/assets.spec.ts +++ b/packages/networks/boilerplate/tests/assets.spec.ts @@ -1,7 +1,256 @@ -import { describe, it, expect } from 'vitest' +import { describe, it, expect, assert } from 'vitest' -describe('example', () => { - it('should work', () => { - expect(1 + 1).toBe(2) +import { NFT } from '../src/assets/NFT.ts' +import { Coin } from '../src/assets/Coin.ts' +import { Token } from '../src/assets/Token.ts' +import { math } from '@multiplechain/utils' +import { Transaction } from '../src/models/Transaction.ts' +import { TransactionStatusEnum } from '@multiplechain/types' +import { TransactionSigner } from '../src/services/TransactionSigner.ts' + +const coinBalanceTestAmount = Number(process.env.BLP_COIN_BALANCE_TEST_AMOUNT) +const tokenBalanceTestAmount = Number(process.env.BLP_TOKEN_BALANCE_TEST_AMOUNT) +const nftBalanceTestAmount = Number(process.env.BLP_NFT_BALANCE_TEST_AMOUNT) +const transferTestAmount = Number(process.env.BLP_TRANSFER_TEST_AMOUNT) +const tokenTransferTestAmount = Number(process.env.BLP_TOKEN_TRANSFER_TEST_AMOUNT) +const tokenApproveTestAmount = Number(process.env.BLP_TOKEN_APPROVE_TEST_AMOUNT) +const nftTransferId = Number(process.env.BLP_NFT_TRANSFER_ID) + +const coinTransferTestIsActive = Boolean(process.env.BLP_COIN_TRANSFER_TEST_IS_ACTIVE !== 'false') +const tokenTransferTestIsActive = Boolean(process.env.BLP_TOKEN_TRANSFER_TEST_IS_ACTIVE !== 'false') +const tokenApproveTestIsActive = Boolean(process.env.BLP_TOKEN_APPROVE_TEST_IS_ACTIVE !== 'false') +const nftTransactionTestIsActive = Boolean( + process.env.BLP_NFT_TRANSACTION_TEST_IS_ACTIVE !== 'false' +) +const tokenTransferFromTestIsActive = Boolean( + process.env.BLP_TOKEN_TRANSFER_FROM_TEST_IS_ACTIVE !== 'false' +) + +const balanceTestAddress = String(process.env.BLP_BALANCE_TEST_ADDRESS) +const senderPrivateKey = String(process.env.BLP_SENDER_PRIVATE_KEY) +const receiverPrivateKey = String(process.env.BLP_RECEIVER_PRIVATE_KEY) +const senderTestAddress = String(process.env.BLP_SENDER_TEST_ADDRESS) +const receiverTestAddress = String(process.env.BLP_RECEIVER_TEST_ADDRESS) +const tokenTestAddress = String(process.env.BLP_TOKEN_TEST_ADDRESS) +const nftTestAddress = String(process.env.BLP_NFT_TEST_ADDRESS) + +const waitSecondsBeforeThanNewTx = async (seconds: number): Promise => { + return await new Promise((resolve) => setTimeout(resolve, seconds * 1000)) +} + +const checkSigner = async (signer: TransactionSigner, privateKey?: string): Promise => { + expect(signer).toBeInstanceOf(TransactionSigner) + + const rawData = signer.getRawData() + + assert.isObject(rawData) + + await signer.sign(privateKey ?? senderPrivateKey) + + assert.isString(signer.getSignedData()) +} + +const checkTx = async (transaction: Transaction): Promise => { + expect(transaction).toBeInstanceOf(Transaction) + const status = await transaction.wait(10000) + expect(status).toBe(TransactionStatusEnum.CONFIRMED) +} + +describe('Coin', () => { + const coin = new Coin() + it('Name and symbol', () => { + expect(coin.getName()).toBe('Boilerplate') + expect(coin.getSymbol()).toBe('BLP') + }) + + it('Decimals', () => { + expect(coin.getDecimals()).toBe(18) + }) + + it('Balance', async () => { + const balance = await coin.getBalance(balanceTestAddress) + expect(balance).toBe(coinBalanceTestAmount) + }) + + it('Transfer', async () => { + const signer = await coin.transfer( + senderTestAddress, + receiverTestAddress, + transferTestAmount + ) + + await checkSigner(signer) + + if (!coinTransferTestIsActive) return + + const beforeBalance = await coin.getBalance(receiverTestAddress) + + await checkTx(await signer.send()) + + const afterBalance = await coin.getBalance(receiverTestAddress) + expect(afterBalance).toBe(math.add(beforeBalance, transferTestAmount)) + }) +}) + +describe('Token', () => { + const token = new Token(tokenTestAddress) + + it('Name and symbol', async () => { + expect(await token.getName()).toBe('TestToken') + expect(await token.getSymbol()).toBe('TTN') + }) + + it('Decimals', async () => { + expect(await token.getDecimals()).toBe(18) + }) + + it('Balance', async () => { + const balance = await token.getBalance(balanceTestAddress) + expect(balance).toBe(tokenBalanceTestAmount) + }) + + it('Total supply', async () => { + const totalSupply = await token.getTotalSupply() + expect(totalSupply).toBe(1000000) + }) + + it('Transfer', async () => { + const signer = await token.transfer( + senderTestAddress, + receiverTestAddress, + tokenTransferTestAmount + ) + + await checkSigner(signer) + + if (!tokenTransferTestIsActive) return + + await waitSecondsBeforeThanNewTx(5) + + const beforeBalance = await token.getBalance(receiverTestAddress) + + await checkTx(await signer.send()) + + const afterBalance = await token.getBalance(receiverTestAddress) + expect(afterBalance).toBe(math.add(beforeBalance, tokenTransferTestAmount)) + }) + + it('Approve and Allowance', async () => { + const signer = await token.approve( + senderTestAddress, + receiverTestAddress, + tokenApproveTestAmount + ) + + await checkSigner(signer) + + if (!tokenApproveTestIsActive) return + + await waitSecondsBeforeThanNewTx(5) + + await checkTx(await signer.send()) + + expect(await token.getAllowance(senderTestAddress, receiverTestAddress)).toBe( + tokenApproveTestAmount + ) + }) + + it('Transfer from', async () => { + const signer = await token.transferFrom( + receiverTestAddress, + senderTestAddress, + receiverTestAddress, + 2 + ) + + await checkSigner(signer, receiverPrivateKey) + + if (!tokenTransferFromTestIsActive) return + + await waitSecondsBeforeThanNewTx(5) + + const beforeBalance = await token.getBalance(receiverTestAddress) + + await checkTx(await signer.send()) + + const afterBalance = await token.getBalance(receiverTestAddress) + expect(afterBalance).toBe(math.add(beforeBalance, 2)) + }) +}) + +describe('Nft', () => { + const nft = new NFT(nftTestAddress) + + it('Name and symbol', async () => { + expect(await nft.getName()).toBe('TestNFT') + expect(await nft.getSymbol()).toBe('TNFT') + }) + + it('Balance', async () => { + const balance = await nft.getBalance(balanceTestAddress) + expect(balance).toBe(nftBalanceTestAmount) + }) + + it('Owner', async () => { + expect(await nft.getOwner(5)).toBe(balanceTestAddress) + }) + + it('Token URI', async () => { + expect(await nft.getTokenURI(5)).toBe('') + }) + + it('Approved', async () => { + expect(await nft.getApproved(5)).toBe(null) + }) + + it('Transfer', async () => { + const signer = await nft.transfer(senderTestAddress, receiverTestAddress, nftTransferId) + + await checkSigner(signer) + + if (!nftTransactionTestIsActive) return + + await waitSecondsBeforeThanNewTx(5) + + await checkTx(await signer.send()) + + expect(await nft.getOwner(nftTransferId)).toBe(receiverTestAddress) + }) + + it('Approve', async () => { + const customOwner = nftTransactionTestIsActive ? receiverTestAddress : senderTestAddress + const customSpender = nftTransactionTestIsActive ? senderTestAddress : receiverTestAddress + const customPrivateKey = nftTransactionTestIsActive ? receiverPrivateKey : senderPrivateKey + + const signer = await nft.approve(customOwner, customSpender, nftTransferId) + + await checkSigner(signer, customPrivateKey) + + if (!nftTransactionTestIsActive) return + + await waitSecondsBeforeThanNewTx(5) + + await checkTx(await signer.send()) + + expect(await nft.getApproved(nftTransferId)).toBe(senderTestAddress) + }) + + it('Transfer from', async () => { + if (!nftTransactionTestIsActive) return + + await waitSecondsBeforeThanNewTx(5) + + const signer = await nft.transferFrom( + senderTestAddress, + receiverTestAddress, + senderTestAddress, + nftTransferId + ) + + await checkSigner(signer) + + await checkTx(await signer.send()) + + expect(await nft.getOwner(nftTransferId)).toBe(senderTestAddress) }) }) diff --git a/packages/networks/boilerplate/tests/models.spec.ts b/packages/networks/boilerplate/tests/models.spec.ts index 34c5579..e3d8ed2 100644 --- a/packages/networks/boilerplate/tests/models.spec.ts +++ b/packages/networks/boilerplate/tests/models.spec.ts @@ -1,7 +1,153 @@ import { describe, it, expect } from 'vitest' -describe('example', () => { - it('should work', () => { - expect(1 + 1).toBe(2) +import { Transaction } from '../src/models/Transaction.ts' +import { NftTransaction } from '../src/models/NftTransaction.ts' +import { CoinTransaction } from '../src/models/CoinTransaction.ts' +import { TokenTransaction } from '../src/models/TokenTransaction.ts' +import { AssetDirectionEnum, TransactionStatusEnum } from '@multiplechain/types' + +const nftId = Number(process.env.BLP_NFT_ID) +const tokenAmount = Number(process.env.BLP_TOKEN_AMOUNT) +const coinAmount = Number(process.env.BLP_COIN_AMOUNT) + +const etherTransferTx = String(process.env.BLP_ETHER_TRANSFER_TX) +const tokenTransferTx = String(process.env.BLP_TOKEN_TRANSFER_TX) +const nftTransferTx = String(process.env.BLP_NFT_TRANSFER_TX) + +const coinSender = String(process.env.BLP_COIN_SENDER) +const coinReceiver = String(process.env.BLP_COIN_RECEIVER) + +const tokenSender = String(process.env.BLP_TOKEN_SENDER) +const tokenReceiver = String(process.env.BLP_TOKEN_RECEIVER) + +const nftSender = String(process.env.BLP_NFT_SENDER) +const nftReceiver = String(process.env.BLP_NFT_RECEIVER) + +describe('Transaction', () => { + const tx = new Transaction(etherTransferTx) + it('Id', async () => { + expect(tx.getId()).toBe(etherTransferTx) + }) + + it('Data', async () => { + expect(await tx.getData()).toBeTypeOf('object') + }) + + it('Wait', async () => { + expect(await tx.wait()).toBe(TransactionStatusEnum.CONFIRMED) + }) + + it('URL', async () => { + expect(tx.getUrl()).toBe('boilerplate url') + }) + + it('Sender', async () => { + expect(await tx.getSigner()).toBe(coinSender) + }) + + it('Fee', async () => { + expect(await tx.getFee()).toBe(0.000371822357865) + }) + + it('Block Number', async () => { + expect(await tx.getBlockNumber()).toBe(5461884) + }) + + it('Block Timestamp', async () => { + expect(await tx.getBlockTimestamp()).toBe(1710141144) + }) + + it('Block Confirmation Count', async () => { + expect(await tx.getBlockConfirmationCount()).toBeGreaterThan(129954) + }) + + it('Status', async () => { + expect(await tx.getStatus()).toBe(TransactionStatusEnum.CONFIRMED) + }) +}) + +describe('Coin Transaction', () => { + const tx = new CoinTransaction(etherTransferTx) + + it('Receiver', async () => { + expect((await tx.getReceiver()).toLowerCase()).toBe(coinReceiver.toLowerCase()) + }) + + it('Amount', async () => { + expect(await tx.getAmount()).toBe(coinAmount) + }) + + it('Verify Transfer', async () => { + expect(await tx.verifyTransfer(AssetDirectionEnum.INCOMING, coinReceiver, coinAmount)).toBe( + TransactionStatusEnum.CONFIRMED + ) + + expect(await tx.verifyTransfer(AssetDirectionEnum.OUTGOING, coinSender, coinAmount)).toBe( + TransactionStatusEnum.CONFIRMED + ) + + expect(await tx.verifyTransfer(AssetDirectionEnum.OUTGOING, coinReceiver, coinAmount)).toBe( + TransactionStatusEnum.FAILED + ) + }) +}) + +describe('Token Transaction', () => { + const tx = new TokenTransaction(tokenTransferTx) + + it('Receiver', async () => { + expect((await tx.getReceiver()).toLowerCase()).toBe(tokenReceiver.toLowerCase()) + }) + + it('Amount', async () => { + expect(await tx.getAmount()).toBe(tokenAmount) + }) + + it('Verify Transfer', async () => { + expect( + await tx.verifyTransfer(AssetDirectionEnum.INCOMING, tokenReceiver, tokenAmount) + ).toBe(TransactionStatusEnum.CONFIRMED) + + expect(await tx.verifyTransfer(AssetDirectionEnum.OUTGOING, tokenSender, tokenAmount)).toBe( + TransactionStatusEnum.CONFIRMED + ) + + expect( + await tx.verifyTransfer(AssetDirectionEnum.OUTGOING, tokenReceiver, tokenAmount) + ).toBe(TransactionStatusEnum.FAILED) + }) +}) + +describe('NFT Transaction', () => { + const tx = new NftTransaction(nftTransferTx) + + it('Receiver', async () => { + expect((await tx.getReceiver()).toLowerCase()).toBe(nftReceiver.toLowerCase()) + }) + + it('Signer', async () => { + expect((await tx.getSigner()).toLowerCase()).toBe(nftReceiver.toLowerCase()) + }) + + it('Sender', async () => { + expect((await tx.getSender()).toLowerCase()).toBe(nftSender.toLowerCase()) + }) + + it('NFT ID', async () => { + expect(await tx.getNftId()).toBe(nftId) + }) + + it('Verify Transfer', async () => { + expect(await tx.verifyTransfer(AssetDirectionEnum.INCOMING, nftReceiver, nftId)).toBe( + TransactionStatusEnum.CONFIRMED + ) + + expect(await tx.verifyTransfer(AssetDirectionEnum.OUTGOING, nftSender, nftId)).toBe( + TransactionStatusEnum.CONFIRMED + ) + + expect(await tx.verifyTransfer(AssetDirectionEnum.OUTGOING, nftReceiver, nftId)).toBe( + TransactionStatusEnum.FAILED + ) }) }) diff --git a/packages/networks/boilerplate/tests/services.spec.ts b/packages/networks/boilerplate/tests/services.spec.ts index 34c5579..aba2b6a 100644 --- a/packages/networks/boilerplate/tests/services.spec.ts +++ b/packages/networks/boilerplate/tests/services.spec.ts @@ -1,7 +1,220 @@ import { describe, it, expect } from 'vitest' -describe('example', () => { - it('should work', () => { - expect(1 + 1).toBe(2) +import { provider } from './setup.ts' +import { Provider } from '../src/services/Provider.ts' + +import { NFT } from '../src/assets/NFT.ts' +import { Coin } from '../src/assets/Coin.ts' +import { Token } from '../src/assets/Token.ts' +import { sleep } from '@multiplechain/utils' +import { TransactionTypeEnum } from '@multiplechain/types' +import { Transaction } from '../src/models/Transaction.ts' +import { NftTransaction } from '../src/models/NftTransaction.ts' +import { CoinTransaction } from '../src/models/CoinTransaction.ts' +import { TokenTransaction } from '../src/models/TokenTransaction.ts' +import { ContractTransaction } from '../src/models/ContractTransaction.ts' +import { TransactionListener } from '../src/services/TransactionListener.ts' + +const senderPrivateKey = String(process.env.BLP_SENDER_PRIVATE_KEY) +const receiverPrivateKey = String(process.env.BLP_RECEIVER_PRIVATE_KEY) +const senderTestAddress = String(process.env.BLP_SENDER_TEST_ADDRESS) +const receiverTestAddress = String(process.env.BLP_RECEIVER_TEST_ADDRESS) +const tokenTestAddress = String(process.env.BLP_TOKEN_TEST_ADDRESS) +const tokenProgram = String(process.env.BLP_TOKEN_PROGRAM) +const nftTestAddress = String(process.env.BLP_NFT_TEST_ADDRESS) +const nftTransferId = String(process.env.BLP_NFT_TRANSFER_ID) + +const transactionListenerTestIsActive = Boolean( + process.env.BLP_TRANSACTION_LISTENER_TEST_IS_ACTIVE !== 'false' +) + +const waitSecondsBeforeThanNewTx = async (seconds: number): Promise => { + return await new Promise((resolve) => setTimeout(resolve, seconds * 1000)) +} + +describe('Provider', () => { + it('isTestnet', () => { + expect(provider.isTestnet()).toBe(true) + }) + + it('instance', () => { + expect(Provider.instance).toBe(provider) + }) + + it('checkRpcConnection', async () => { + expect(await provider.checkRpcConnection()).toBe(true) + }) + + it('checkWsConnection', async () => { + expect(await provider.checkWsConnection()).toBe(true) + }) +}) + +describe('Transaction Listener', () => { + if (!transactionListenerTestIsActive) { + it('No test is active', () => { + expect(true).toBe(true) + }) + return + } + + it('General', async () => { + const listener = new TransactionListener(TransactionTypeEnum.GENERAL, { + signer: senderTestAddress + }) + + const signer = await new Coin().transfer(senderTestAddress, receiverTestAddress, 0.0001) + + const waitListenerEvent = async (): Promise => { + return await new Promise((resolve, reject) => { + void listener + .on((transaction) => { + listener.stop() + resolve(transaction) + }) + .then(async () => { + await sleep(2000) + void (await signer.sign(senderPrivateKey)).send() + }) + .catch(reject) + }) + } + + expect(await waitListenerEvent()).toBeInstanceOf(Transaction) + }) + + it('Contract', async () => { + await waitSecondsBeforeThanNewTx(10) + + const listener = new TransactionListener(TransactionTypeEnum.CONTRACT, { + signer: senderTestAddress, + address: tokenProgram + }) + + const signer = await new Token(tokenTestAddress).transfer( + senderTestAddress, + receiverTestAddress, + 0.01 + ) + + const waitListenerEvent = async (): Promise => { + return await new Promise((resolve, reject) => { + void listener + .on((transaction) => { + listener.stop() + resolve(transaction) + }) + .then(async () => { + await sleep(2000) + void (await signer.sign(senderPrivateKey)).send() + }) + .catch(reject) + }) + } + + expect(await waitListenerEvent()).toBeInstanceOf(ContractTransaction) + }) + + it('Coin', async () => { + await waitSecondsBeforeThanNewTx(10) + + const listener = new TransactionListener(TransactionTypeEnum.COIN, { + signer: senderTestAddress, + receiver: receiverTestAddress + }) + + const signer = await new Coin().transfer(senderTestAddress, receiverTestAddress, 0.0001) + + const waitListenerEvent = async (): Promise => { + return await new Promise((resolve, reject) => { + void listener + .on((transaction) => { + listener.stop() + resolve(transaction) + }) + .then(async () => { + await sleep(2000) + void (await signer.sign(senderPrivateKey)).send() + }) + .catch(reject) + }) + } + + expect(await waitListenerEvent()).toBeInstanceOf(CoinTransaction) + }) + + it('Token', async () => { + await waitSecondsBeforeThanNewTx(10) + + const listener = new TransactionListener(TransactionTypeEnum.TOKEN, { + signer: senderTestAddress, + receiver: receiverTestAddress, + address: tokenTestAddress + }) + + const signer = await new Token(tokenTestAddress).transfer( + senderTestAddress, + receiverTestAddress, + 0.01 + ) + + const waitListenerEvent = async (): Promise => { + return await new Promise((resolve, reject) => { + void listener + .on((transaction) => { + listener.stop() + resolve(transaction) + }) + .then(async () => { + await sleep(2000) + void (await signer.sign(senderPrivateKey)).send() + }) + .catch(reject) + }) + } + + expect(await waitListenerEvent()).toBeInstanceOf(TokenTransaction) + }) + + it('NFT', async () => { + await waitSecondsBeforeThanNewTx(10) + + const listener = new TransactionListener(TransactionTypeEnum.NFT, { + signer: senderTestAddress, + receiver: receiverTestAddress, + address: nftTestAddress, + nftId: nftTransferId + }) + + const nft = new NFT(nftTestAddress) + const signer = await nft.transfer(senderTestAddress, receiverTestAddress, nftTransferId) + + const waitListenerEvent = async (): Promise => { + return await new Promise((resolve, reject) => { + void listener + .on((transaction) => { + listener.stop() + resolve(transaction) + }) + .then(async () => { + await sleep(2000) + void (await signer.sign(senderPrivateKey)).send() + }) + .catch(reject) + }) + } + + const transaction = await waitListenerEvent() + expect(transaction).toBeInstanceOf(NftTransaction) + await transaction.wait() + await waitSecondsBeforeThanNewTx(10) + + const newSigner = await nft.transfer( + receiverTestAddress, + senderTestAddress, + nftTransferId + ) + + void (await newSigner.sign(receiverPrivateKey)).send() }) }) From b06b9371c05dad12aa7976220ccc09d9f64abc87 Mon Sep 17 00:00:00 2001 From: Halil Beycan <50718965+BeycanDeveloper@users.noreply.github.com> Date: Tue, 21 May 2024 12:49:25 +0800 Subject: [PATCH 64/90] listeners excluded --- vitest.config.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/vitest.config.ts b/vitest.config.ts index 01ebc40..e153ac5 100644 --- a/vitest.config.ts +++ b/vitest.config.ts @@ -10,17 +10,17 @@ export default mergeConfig( provider: 'istanbul', include: ['**/packages/**/src/**', '**/packages/networks/**/src/**'], exclude: [ - '**/boilerplate/**', '**/types/**', '**/browser/**', '**/index.ts/**', + '**/boilerplate/**', '**/bitcoin/src/assets/NFT.ts', '**/bitcoin/src/assets/Token.ts', '**/bitcoin/src/assets/Contract.ts', '**/bitcoin/src/models/NftTransaction.ts', '**/bitcoin/src/models/TokenTransaction.ts', '**/bitcoin/src/models/ContractTransaction.ts', - '**/tron/src/services/TransactionListener.ts' + '**/networks/**/src/services/TransactionListener.ts' ] }, watch: false, From 09a7ae56b48e3796e90861fd72b753bf08948b96 Mon Sep 17 00:00:00 2001 From: Halil Beycan <50718965+BeycanDeveloper@users.noreply.github.com> Date: Tue, 21 May 2024 13:38:47 +0800 Subject: [PATCH 65/90] types exported --- packages/types/src/enums.ts | 9 ++++++++- .../src/services/TransactionListenerInterface.ts | 15 +++++++++------ 2 files changed, 17 insertions(+), 7 deletions(-) diff --git a/packages/types/src/enums.ts b/packages/types/src/enums.ts index f086e3a..3992dd9 100644 --- a/packages/types/src/enums.ts +++ b/packages/types/src/enums.ts @@ -34,6 +34,8 @@ export enum ErrorTypeEnum { RPC_TIMEOUT = 'RPC_TIMEOUT', RPC_REQUEST_ERROR = 'RPC_REQUEST_ERROR', RPC_ACCESS_DENIED = 'RPC_ACCESS_DENIED', + WS_URL_NOT_DEFINED = 'WS_URL_NOT_DEFINED', + WS_CONNECTION_FAILED = 'WS_CONNECTION_FAILED', UNACCEPTED_CHAIN = 'UNACCEPTED_CHAIN', UNAUTHORIZED_ADDRESS = 'UNAUTHORIZED_ADDRESS', INSUFFICIENT_BALANCE = 'INSUFFICIENT_BALANCE', @@ -42,6 +44,7 @@ export enum ErrorTypeEnum { INVALID_PRIVATE_KEY = 'INVALID_PRIVATE_KEY', INVALID_PUBLIC_KEY = 'INVALID_PUBLIC_KEY', INVALID_TRANSACTION_ID = 'INVALID_TRANSACTION_ID', + PROVIDER_IS_REQUIRED = 'PROVIDER_IS_REQUIRED', PROVIDER_IS_NOT_INITIALIZED = 'PROVIDER_IS_NOT_INITIALIZED', PROVIDER_IS_ALREADY_INITIALIZED = 'PROVIDER_IS_ALREADY_INITIALIZED', WALLET_ALREADY_PROCESSING = 'WALLET_ALREADY_PROCESSING', @@ -50,7 +53,11 @@ export enum ErrorTypeEnum { WALLET_CONNECTION_FAILED = 'WALLET_CONNECTION_FAILED', WALLET_CONNECTION_TIMEOUT = 'WALLET_CONNECTION_TIMEOUT', TRANSACTION_CREATION_FAILED = 'TRANSACTION_CREATION_FAILED', - CLOSED_WALLETCONNECT_MODAL = 'CLOSED_WALLETCONNECT_MODAL' + TRANSACTION_NOT_FOUND = 'TRANSACTION_NOT_FOUND', + CLOSED_WALLETCONNECT_MODAL = 'CLOSED_WALLETCONNECT_MODAL', + PROJECT_ID_IS_REQUIRED = 'PROJECT_ID_IS_REQUIRED', + METADATA_IS_REQUIRED = 'METADATA_IS_REQUIRED', + OPS_IS_REQUIRED = 'OPS_IS_REQUIRED' } export enum WalletPlatformEnum { diff --git a/packages/types/src/services/TransactionListenerInterface.ts b/packages/types/src/services/TransactionListenerInterface.ts index ff277ac..526d568 100644 --- a/packages/types/src/services/TransactionListenerInterface.ts +++ b/packages/types/src/services/TransactionListenerInterface.ts @@ -11,30 +11,33 @@ import { TransactionTypeEnum } from '../enums.ts' /** * Filter types for each transaction type in TransactionListenerInterface */ -interface TransactionListenerFilterInterface { +export interface TransactionListenerFilterInterface { signer?: string } -interface ContractTransactionListenerFilterInterface extends TransactionListenerFilterInterface { +export interface ContractTransactionListenerFilterInterface + extends TransactionListenerFilterInterface { address?: string } -interface AssetTransactionListenerFilterInterface extends TransactionListenerFilterInterface { +export interface AssetTransactionListenerFilterInterface + extends TransactionListenerFilterInterface { sender?: string receiver?: string } -interface CoinTransactionListenerFilterInterface extends AssetTransactionListenerFilterInterface { +export interface CoinTransactionListenerFilterInterface + extends AssetTransactionListenerFilterInterface { amount?: number } -interface TokenTransactionListenerFilterInterface +export interface TokenTransactionListenerFilterInterface extends AssetTransactionListenerFilterInterface, ContractTransactionListenerFilterInterface { amount?: number } -interface NftTransactionListenerFilterInterface +export interface NftTransactionListenerFilterInterface extends AssetTransactionListenerFilterInterface, ContractTransactionListenerFilterInterface { nftId?: number | string From 225a40d0f785a7b6efa060fda34cade831666dfc Mon Sep 17 00:00:00 2001 From: Halil Beycan <50718965+BeycanDeveloper@users.noreply.github.com> Date: Tue, 21 May 2024 14:55:39 +0800 Subject: [PATCH 66/90] types updated for dynamic callback transaction parameter --- packages/types/package.json | 2 +- .../services/TransactionListenerInterface.ts | 86 ++++++++++--------- 2 files changed, 45 insertions(+), 43 deletions(-) diff --git a/packages/types/package.json b/packages/types/package.json index e086b85..6422f7f 100644 --- a/packages/types/package.json +++ b/packages/types/package.json @@ -1,6 +1,6 @@ { "name": "@multiplechain/types", - "version": "0.1.55", + "version": "0.1.56", "type": "module", "main": "./src/index.ts", "types": "./src/index.ts", diff --git a/packages/types/src/services/TransactionListenerInterface.ts b/packages/types/src/services/TransactionListenerInterface.ts index 526d568..f86e3a9 100644 --- a/packages/types/src/services/TransactionListenerInterface.ts +++ b/packages/types/src/services/TransactionListenerInterface.ts @@ -1,11 +1,3 @@ -import type { - TransactionInterface, - ContractTransactionInterface, - CoinTransactionInterface, - TokenTransactionInterface, - NftTransactionInterface -} from '../models.ts' - import { TransactionTypeEnum } from '../enums.ts' /** @@ -46,24 +38,6 @@ export interface NftTransactionListenerFilterInterface * Filter types for each transaction type in TransactionListenerInterface */ -/** - * 'DynamicTransactionType' connects transaction types to their corresponding transaction interfaces - * Every type of transaction has its own unique transaction interface. - * A sender's wallet address is a common value. - */ -export type DynamicTransactionType = - T extends TransactionTypeEnum.GENERAL - ? TransactionInterface - : T extends TransactionTypeEnum.CONTRACT - ? ContractTransactionInterface - : T extends TransactionTypeEnum.COIN - ? CoinTransactionInterface - : T extends TransactionTypeEnum.TOKEN - ? TokenTransactionInterface - : T extends TransactionTypeEnum.NFT - ? NftTransactionInterface - : never - /** * 'DynamicTransactionListenerFilterInterface' connects transaction types to their corresponding filter interfaces * Every type of transaction has its own unique filter values. @@ -95,24 +69,42 @@ export const TransactionListenerProcessIndex = { } /** - * 'TransactionListenerCallbackType' is a type of function that is triggered when a transaction is detected. - * It takes a transaction as an argument. + * Dynamic types for transaction trigger and callback methods */ -export type TransactionListenerCallbackType = ( - transaction: DynamicTransactionType -) => void - -export interface TransactionListenerInterface { +/** + * 'DynamicTransactionType' connects transaction types to their corresponding transaction interfaces + * Every type of transaction has its own unique transaction interface. + * A sender's wallet address is a common value. + */ +export type DynamicTransactionType< + T extends TransactionTypeEnum, + Transaction, + ContractTransaction, + CoinTransaction, + TokenTransaction, + NftTransaction +> = T extends TransactionTypeEnum.GENERAL + ? Transaction + : T extends TransactionTypeEnum.CONTRACT + ? ContractTransaction + : T extends TransactionTypeEnum.COIN + ? CoinTransaction + : T extends TransactionTypeEnum.TOKEN + ? TokenTransaction + : T extends TransactionTypeEnum.NFT + ? NftTransaction + : never + +export interface TransactionListenerInterface< + T extends TransactionTypeEnum, + Transaction, + CallBackType +> { /** * The 'type' property is a generic type that is used to define the type of transaction listener. */ type: T - /** - * 'callback' is an array of callback functions that are triggered when a transaction is detected. - */ - callbacks: TransactionListenerCallbackType[] - /** * 'status' is a boolean that shows the status of the listener. * If 'status' is true, the listener is active. @@ -120,6 +112,16 @@ export interface TransactionListenerInterface { */ status: boolean + /** + * 'callback' is an array of callback functions that are triggered when a transaction is detected. + */ + callbacks: CallBackType[] + + /** + * Triggered transactions + */ + triggeredTransactions: string[] + /** * 'filter' is an object that has values depending on transaction listener type. * E.g. no matter which type of transaction is listening, 'filter' has to have a 'sender' value @@ -147,17 +149,17 @@ export interface TransactionListenerInterface { /** * on() method is a listener that listens to the transaction events. * When a transaction is detected, it triggers the event. - * @param {TransactionListenerCallbackType} callback - a function that is triggered when a transaction is detected. + * @param {CallBackType} callback - a function that is triggered when a transaction is detected. * @return {Promise} */ - on: (callback: TransactionListenerCallbackType) => Promise + on: (callback: CallBackType) => Promise /** * trigger() method triggers the event when a transaction is detected. - * @param {DynamicTransactionType} transaction - a transaction that is detected. + * @param {Transaction} transaction - a transaction that is detected. * @return {void} */ - trigger: (transaction: DynamicTransactionType) => void + trigger: (transaction: Transaction) => void /** * listener methods for each transaction type From 94a8075a8fdf4b433515161b4e04b2ac35f6aa35 Mon Sep 17 00:00:00 2001 From: Halil Beycan <50718965+BeycanDeveloper@users.noreply.github.com> Date: Tue, 21 May 2024 15:03:14 +0800 Subject: [PATCH 67/90] updated --- packages/networks/boilerplate/package.json | 2 +- packages/networks/boilerplate/pnpm-lock.yaml | 8 +-- .../src/services/TransactionListener.ts | 63 ++++++++++++------- 3 files changed, 47 insertions(+), 26 deletions(-) diff --git a/packages/networks/boilerplate/package.json b/packages/networks/boilerplate/package.json index 1afce77..2cba041 100644 --- a/packages/networks/boilerplate/package.json +++ b/packages/networks/boilerplate/package.json @@ -62,7 +62,7 @@ "url": "https://github.com/MultipleChain/js/issues" }, "dependencies": { - "@multiplechain/types": "^0.1.55", + "@multiplechain/types": "^0.1.56", "@multiplechain/utils": "^0.1.18" } } \ No newline at end of file diff --git a/packages/networks/boilerplate/pnpm-lock.yaml b/packages/networks/boilerplate/pnpm-lock.yaml index aae81e5..1a44c34 100644 --- a/packages/networks/boilerplate/pnpm-lock.yaml +++ b/packages/networks/boilerplate/pnpm-lock.yaml @@ -6,16 +6,16 @@ settings: dependencies: '@multiplechain/types': - specifier: ^0.1.55 - version: 0.1.55 + specifier: ^0.1.56 + version: 0.1.56 '@multiplechain/utils': specifier: ^0.1.18 version: 0.1.18 packages: - /@multiplechain/types@0.1.55: - resolution: {integrity: sha512-9fYrLaDxX2pj9zfIbmvk1hPF3FH/bK+Q3uTF+k3zdsitP/HzQ1S9zImNz20Tvoqkk1ns+/8ecE0Y6GNowsDOQA==} + /@multiplechain/types@0.1.56: + resolution: {integrity: sha512-tnkgDwW0AWxEfhE/392LR6ZPE7Pxz5/Ei1XYsQISGkOfYYZrsvJXr69fXTjDOHCq7RCuQqytKmhnKs5K4xHd7w==} dev: false /@multiplechain/utils@0.1.18: diff --git a/packages/networks/boilerplate/src/services/TransactionListener.ts b/packages/networks/boilerplate/src/services/TransactionListener.ts index da72fc3..4581048 100644 --- a/packages/networks/boilerplate/src/services/TransactionListener.ts +++ b/packages/networks/boilerplate/src/services/TransactionListener.ts @@ -1,16 +1,39 @@ +import { Provider } from './Provider.ts' +import { Transaction } from '../models/Transaction.ts' +import { NftTransaction } from '../models/NftTransaction.ts' +import { CoinTransaction } from '../models/CoinTransaction.ts' +import { TokenTransaction } from '../models/TokenTransaction.ts' +import { ContractTransaction } from '../models/ContractTransaction.ts' +import { TransactionListenerProcessIndex, TransactionTypeEnum } from '@multiplechain/types' import type { - TransactionTypeEnum, DynamicTransactionType, TransactionListenerInterface, - TransactionListenerCallbackType, - DynamicTransactionListenerFilterType + DynamicTransactionListenerFilterType, + NftTransactionListenerFilterInterface, + TokenTransactionListenerFilterInterface, + CoinTransactionListenerFilterInterface, + ContractTransactionListenerFilterInterface } from '@multiplechain/types' -import { Provider } from './Provider.ts' -import { TransactionListenerProcessIndex } from '@multiplechain/types' - -export class TransactionListener - implements TransactionListenerInterface +type TransactionListenerTriggerType = DynamicTransactionType< + T, + Transaction, + ContractTransaction, + CoinTransaction, + TokenTransaction, + NftTransaction +> + +type TransactionListenerCallbackType< + T extends TransactionTypeEnum, + Transaction = TransactionListenerTriggerType +> = (transaction: Transaction) => void + +export class TransactionListener< + T extends TransactionTypeEnum, + DTransaction extends TransactionListenerTriggerType, + CallBackType extends TransactionListenerCallbackType +> implements TransactionListenerInterface { /** * Transaction type @@ -20,7 +43,7 @@ export class TransactionListener /** * Transaction listener callback */ - callbacks: TransactionListenerCallbackType[] = [] + callbacks: CallBackType[] = [] /** * Transaction listener filter @@ -86,24 +109,24 @@ export class TransactionListener /** * Listen to the transaction events - * @param {TransactionListenerCallbackType} callback - Transaction listener callback + * @param {CallBackType} callback - Transaction listener callback * @returns {Promise} */ - async on(callback: TransactionListenerCallbackType): Promise { + async on(callback: CallBackType): Promise { this.callbacks.push(callback) return true } /** * Trigger the event when a transaction is detected - * @param {DynamicTransactionType} transaction - Transaction data + * @param {TransactionListenerTriggerType} transaction - Transaction data * @returns {void} */ - trigger(transaction: DynamicTransactionType): void { + trigger(transaction: TransactionListenerTriggerType): void { if (!this.triggeredTransactions.includes(transaction.id)) { this.triggeredTransactions.push(transaction.id) this.callbacks.forEach((callback) => { - callback(transaction) + callback(transaction as unknown as DTransaction) }) } } @@ -112,16 +135,14 @@ export class TransactionListener * General transaction process * @returns {void} */ - generalProcess(): void { - // General transaction process - } + generalProcess(): void {} /** * Contract transaction process * @returns {void} */ contractProcess(): void { - // Contract transaction process + const filter = this.filter as ContractTransactionListenerFilterInterface } /** @@ -129,7 +150,7 @@ export class TransactionListener * @returns {void} */ coinProcess(): void { - // Coin transaction process + const filter = this.filter as CoinTransactionListenerFilterInterface } /** @@ -137,7 +158,7 @@ export class TransactionListener * @returns {void} */ tokenProcess(): void { - // Token transaction process + const filter = this.filter as TokenTransactionListenerFilterInterface } /** @@ -145,6 +166,6 @@ export class TransactionListener * @returns {void} */ nftProcess(): void { - // NFT transaction process + const filter = this.filter as NftTransactionListenerFilterInterface } } From 432c4c54af241d096539e7794c19d2cb5b5d3c6a Mon Sep 17 00:00:00 2001 From: Halil Beycan <50718965+BeycanDeveloper@users.noreply.github.com> Date: Tue, 21 May 2024 15:11:52 +0800 Subject: [PATCH 68/90] updated for new types --- packages/networks/solana/package.json | 4 +- packages/networks/solana/pnpm-lock.yaml | 8 +-- .../src/services/TransactionListener.ts | 65 ++++++++++++------- 3 files changed, 48 insertions(+), 29 deletions(-) diff --git a/packages/networks/solana/package.json b/packages/networks/solana/package.json index fa7f4ea..e62763a 100644 --- a/packages/networks/solana/package.json +++ b/packages/networks/solana/package.json @@ -1,6 +1,6 @@ { "name": "@multiplechain/solana", - "version": "0.1.0", + "version": "0.4.0", "type": "module", "main": "dist/index.cjs", "module": "dist/index.es.js", @@ -63,7 +63,7 @@ }, "dependencies": { "@metaplex-foundation/js": "^0.20.1", - "@multiplechain/types": "^0.1.55", + "@multiplechain/types": "^0.1.56", "@multiplechain/utils": "^0.1.18", "@solana/spl-token": "^0.4.6", "@solana/spl-token-metadata": "^0.1.4", diff --git a/packages/networks/solana/pnpm-lock.yaml b/packages/networks/solana/pnpm-lock.yaml index 77b381a..2f99a0a 100644 --- a/packages/networks/solana/pnpm-lock.yaml +++ b/packages/networks/solana/pnpm-lock.yaml @@ -9,8 +9,8 @@ dependencies: specifier: ^0.20.1 version: 0.20.1(arweave@1.15.1)(fastestsmallesttextencoderdecoder@1.0.22) '@multiplechain/types': - specifier: ^0.1.55 - version: 0.1.55 + specifier: ^0.1.56 + version: 0.1.56 '@multiplechain/utils': specifier: ^0.1.18 version: 0.1.18 @@ -620,8 +620,8 @@ packages: - utf-8-validate dev: false - /@multiplechain/types@0.1.55: - resolution: {integrity: sha512-9fYrLaDxX2pj9zfIbmvk1hPF3FH/bK+Q3uTF+k3zdsitP/HzQ1S9zImNz20Tvoqkk1ns+/8ecE0Y6GNowsDOQA==} + /@multiplechain/types@0.1.56: + resolution: {integrity: sha512-tnkgDwW0AWxEfhE/392LR6ZPE7Pxz5/Ei1XYsQISGkOfYYZrsvJXr69fXTjDOHCq7RCuQqytKmhnKs5K4xHd7w==} dev: false /@multiplechain/utils@0.1.18: diff --git a/packages/networks/solana/src/services/TransactionListener.ts b/packages/networks/solana/src/services/TransactionListener.ts index 3643d46..b3c1a7c 100644 --- a/packages/networks/solana/src/services/TransactionListener.ts +++ b/packages/networks/solana/src/services/TransactionListener.ts @@ -1,12 +1,11 @@ -import type { - DynamicTransactionType, - TransactionListenerInterface, - TransactionListenerCallbackType, - DynamicTransactionListenerFilterType -} from '@multiplechain/types' - import { Provider } from './Provider.ts' import { Transaction } from '../models/Transaction.ts' +import { objectsEqual } from '@multiplechain/utils' +import { NftTransaction } from '../models/NftTransaction.ts' +import { CoinTransaction } from '../models/CoinTransaction.ts' +import { TokenTransaction } from '../models/TokenTransaction.ts' +import { ContractTransaction } from '../models/ContractTransaction.ts' +import { getAssociatedTokenAddressSync } from '@solana/spl-token' import { PublicKey, SystemProgram, @@ -16,16 +15,36 @@ import { type ParsedInstruction, type PartiallyDecodedInstruction } from '@solana/web3.js' -import { objectsEqual } from '@multiplechain/utils' -import { NftTransaction } from '../models/NftTransaction.ts' -import { CoinTransaction } from '../models/CoinTransaction.ts' -import { TokenTransaction } from '../models/TokenTransaction.ts' -import { ContractTransaction } from '../models/ContractTransaction.ts' -import { TransactionListenerProcessIndex, TransactionTypeEnum } from '@multiplechain/types' -import { getAssociatedTokenAddressSync } from '@solana/spl-token' +import type { + DynamicTransactionType, + TransactionListenerInterface, + DynamicTransactionListenerFilterType +} from '@multiplechain/types' +import { + ErrorTypeEnum, + TransactionTypeEnum, + TransactionListenerProcessIndex +} from '@multiplechain/types' -export class TransactionListener - implements TransactionListenerInterface +type TransactionListenerTriggerType = DynamicTransactionType< + T, + Transaction, + ContractTransaction, + CoinTransaction, + TokenTransaction, + NftTransaction +> + +type TransactionListenerCallbackType< + T extends TransactionTypeEnum, + Transaction = TransactionListenerTriggerType +> = (transaction: Transaction) => void + +export class TransactionListener< + T extends TransactionTypeEnum, + DTransaction extends TransactionListenerTriggerType, + CallBackType extends TransactionListenerCallbackType +> implements TransactionListenerInterface { /** * Transaction type @@ -35,7 +54,7 @@ export class TransactionListener /** * Transaction listener callback */ - callbacks: TransactionListenerCallbackType[] = [] + callbacks: CallBackType[] = [] /** * Transaction listener filter @@ -111,13 +130,13 @@ export class TransactionListener /** * Listen to the transaction events - * @param {TransactionListenerCallbackType} callback - Transaction listener callback + * @param {CallBackType} callback - Transaction listener callback * @returns {Promise} */ - async on(callback: TransactionListenerCallbackType): Promise { + async on(callback: CallBackType): Promise { if (!this.connected) { if ((await this.provider.checkWsConnection()) instanceof Error) { - throw new Error('WebSocket connection is not available') + throw new Error(ErrorTypeEnum.WS_CONNECTION_FAILED) } else { this.connected = true } @@ -131,14 +150,14 @@ export class TransactionListener /** * Trigger the event when a transaction is detected - * @param {DynamicTransactionType} transaction - Transaction data + * @param {TransactionListenerTriggerType} transaction - Transaction data * @returns {void} */ - trigger(transaction: DynamicTransactionType): void { + trigger(transaction: TransactionListenerTriggerType): void { if (!this.triggeredTransactions.includes(transaction.id)) { this.triggeredTransactions.push(transaction.id) this.callbacks.forEach((callback) => { - callback(transaction) + callback(transaction as unknown as DTransaction) }) } } From 040d52ff0b00ec56c2ae7043d9be1408e7f32bb6 Mon Sep 17 00:00:00 2001 From: Halil Beycan <50718965+BeycanDeveloper@users.noreply.github.com> Date: Tue, 21 May 2024 15:16:52 +0800 Subject: [PATCH 69/90] added new method --- packages/utils/package.json | 2 +- packages/utils/src/index.ts | 18 ++++++++++++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/packages/utils/package.json b/packages/utils/package.json index 73416fc..7665b4c 100644 --- a/packages/utils/package.json +++ b/packages/utils/package.json @@ -1,6 +1,6 @@ { "name": "@multiplechain/utils", - "version": "0.1.18", + "version": "0.1.20", "type": "module", "main": "./src/index.ts", "types": "./src/index.ts", diff --git a/packages/utils/src/index.ts b/packages/utils/src/index.ts index 95b7f63..64739d3 100644 --- a/packages/utils/src/index.ts +++ b/packages/utils/src/index.ts @@ -108,6 +108,24 @@ export const objectsEqual = (o1: object, o2: object): boolean => { return JSON.stringify(o1) === JSON.stringify(o2) } +/** + * Converts the given number to a readable string + * @param {number} num + * @returns string + */ +export const toReadableString = (num: number): string => { + const [coefficient, exponent] = num + .toExponential() + .split('e') + .map((item) => parseFloat(item)) + + let result = (coefficient * Math.pow(10, exponent)).toString() + + result = parseFloat(result).toString() + + return result +} + /** * checks if the given url is a valid websocket url * @param {string} url From 0a627f4560b73f95ce664cd7711dbc0c44ca598a Mon Sep 17 00:00:00 2001 From: Halil Beycan <50718965+BeycanDeveloper@users.noreply.github.com> Date: Tue, 21 May 2024 15:17:40 +0800 Subject: [PATCH 70/90] updated --- packages/networks/boilerplate/package.json | 2 +- packages/networks/boilerplate/pnpm-lock.yaml | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/networks/boilerplate/package.json b/packages/networks/boilerplate/package.json index 2cba041..9e3607a 100644 --- a/packages/networks/boilerplate/package.json +++ b/packages/networks/boilerplate/package.json @@ -63,6 +63,6 @@ }, "dependencies": { "@multiplechain/types": "^0.1.56", - "@multiplechain/utils": "^0.1.18" + "@multiplechain/utils": "^0.1.20" } } \ No newline at end of file diff --git a/packages/networks/boilerplate/pnpm-lock.yaml b/packages/networks/boilerplate/pnpm-lock.yaml index 1a44c34..08e12c2 100644 --- a/packages/networks/boilerplate/pnpm-lock.yaml +++ b/packages/networks/boilerplate/pnpm-lock.yaml @@ -9,8 +9,8 @@ dependencies: specifier: ^0.1.56 version: 0.1.56 '@multiplechain/utils': - specifier: ^0.1.18 - version: 0.1.18 + specifier: ^0.1.20 + version: 0.1.20 packages: @@ -18,8 +18,8 @@ packages: resolution: {integrity: sha512-tnkgDwW0AWxEfhE/392LR6ZPE7Pxz5/Ei1XYsQISGkOfYYZrsvJXr69fXTjDOHCq7RCuQqytKmhnKs5K4xHd7w==} dev: false - /@multiplechain/utils@0.1.18: - resolution: {integrity: sha512-UCoOOBJrawp/lInepxuoEiYwId0wMPg7rX8p78FLqzGl8f/b93sAtv7sP87/VVKwhdoEuNZ/uQjckycmNeks/w==} + /@multiplechain/utils@0.1.20: + resolution: {integrity: sha512-4eEs4YR/V4F2Qnkl5KTZvPpewRQiX7C193d0tjpQuIfyumTEBJtdHYm1CW9CoJ6EjQUaB0oqSRKXomhzfK1qkw==} dependencies: '@types/ws': 8.5.10 bignumber.js: 9.1.2 From 6a2d045c9b32067e70dcc6987c51af8794f066c1 Mon Sep 17 00:00:00 2001 From: Halil Beycan <50718965+BeycanDeveloper@users.noreply.github.com> Date: Tue, 21 May 2024 15:21:28 +0800 Subject: [PATCH 71/90] updated for utils --- packages/networks/solana/package.json | 2 +- packages/networks/solana/pnpm-lock.yaml | 8 ++++---- packages/networks/solana/src/index.ts | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/networks/solana/package.json b/packages/networks/solana/package.json index e62763a..4aa9409 100644 --- a/packages/networks/solana/package.json +++ b/packages/networks/solana/package.json @@ -64,7 +64,7 @@ "dependencies": { "@metaplex-foundation/js": "^0.20.1", "@multiplechain/types": "^0.1.56", - "@multiplechain/utils": "^0.1.18", + "@multiplechain/utils": "^0.1.20", "@solana/spl-token": "^0.4.6", "@solana/spl-token-metadata": "^0.1.4", "@solana/web3.js": "^1.91.8", diff --git a/packages/networks/solana/pnpm-lock.yaml b/packages/networks/solana/pnpm-lock.yaml index 2f99a0a..eeb2be6 100644 --- a/packages/networks/solana/pnpm-lock.yaml +++ b/packages/networks/solana/pnpm-lock.yaml @@ -12,8 +12,8 @@ dependencies: specifier: ^0.1.56 version: 0.1.56 '@multiplechain/utils': - specifier: ^0.1.18 - version: 0.1.18 + specifier: ^0.1.20 + version: 0.1.20 '@solana/spl-token': specifier: ^0.4.6 version: 0.4.6(@solana/web3.js@1.91.8)(fastestsmallesttextencoderdecoder@1.0.22) @@ -624,8 +624,8 @@ packages: resolution: {integrity: sha512-tnkgDwW0AWxEfhE/392LR6ZPE7Pxz5/Ei1XYsQISGkOfYYZrsvJXr69fXTjDOHCq7RCuQqytKmhnKs5K4xHd7w==} dev: false - /@multiplechain/utils@0.1.18: - resolution: {integrity: sha512-UCoOOBJrawp/lInepxuoEiYwId0wMPg7rX8p78FLqzGl8f/b93sAtv7sP87/VVKwhdoEuNZ/uQjckycmNeks/w==} + /@multiplechain/utils@0.1.20: + resolution: {integrity: sha512-4eEs4YR/V4F2Qnkl5KTZvPpewRQiX7C193d0tjpQuIfyumTEBJtdHYm1CW9CoJ6EjQUaB0oqSRKXomhzfK1qkw==} dependencies: '@types/ws': 8.5.10 bignumber.js: 9.1.2 diff --git a/packages/networks/solana/src/index.ts b/packages/networks/solana/src/index.ts index 668ab52..7b0e1cd 100644 --- a/packages/networks/solana/src/index.ts +++ b/packages/networks/solana/src/index.ts @@ -4,5 +4,5 @@ export * as assets from './assets/index.ts' export * as models from './models/index.ts' export * as services from './services/index.ts' -export * as utils from '@multiplechain/utils' +export * as utils from './utils.ts' export * as types from '@multiplechain/types' From 975db1901bcc04e11b7c131a3a9cddc117da8b72 Mon Sep 17 00:00:00 2001 From: Halil Beycan <50718965+BeycanDeveloper@users.noreply.github.com> Date: Tue, 21 May 2024 15:25:38 +0800 Subject: [PATCH 72/90] updated for new types --- packages/networks/bitcoin/package.json | 6 +-- packages/networks/bitcoin/pnpm-lock.yaml | 16 +++---- .../bitcoin/src/models/Transaction.ts | 2 +- .../src/services/TransactionListener.ts | 45 +++++++++++++------ 4 files changed, 44 insertions(+), 25 deletions(-) diff --git a/packages/networks/bitcoin/package.json b/packages/networks/bitcoin/package.json index e7b2c77..7040f81 100644 --- a/packages/networks/bitcoin/package.json +++ b/packages/networks/bitcoin/package.json @@ -1,6 +1,6 @@ { "name": "@multiplechain/bitcoin", - "version": "0.1.0", + "version": "0.4.0", "type": "module", "main": "dist/index.cjs", "module": "dist/index.es.js", @@ -62,8 +62,8 @@ "url": "https://github.com/MultipleChain/js/issues" }, "dependencies": { - "@multiplechain/types": "^0.1.55", - "@multiplechain/utils": "^0.1.18", + "@multiplechain/types": "^0.1.56", + "@multiplechain/utils": "^0.1.20", "axios": "^1.6.8", "bitcore-lib": "^10.0.28", "sats-connect": "^2.3.1", diff --git a/packages/networks/bitcoin/pnpm-lock.yaml b/packages/networks/bitcoin/pnpm-lock.yaml index 5492145..3cc25a4 100644 --- a/packages/networks/bitcoin/pnpm-lock.yaml +++ b/packages/networks/bitcoin/pnpm-lock.yaml @@ -6,11 +6,11 @@ settings: dependencies: '@multiplechain/types': - specifier: ^0.1.55 - version: 0.1.55 + specifier: ^0.1.56 + version: 0.1.56 '@multiplechain/utils': - specifier: ^0.1.18 - version: 0.1.18 + specifier: ^0.1.20 + version: 0.1.20 axios: specifier: ^1.6.8 version: 1.6.8 @@ -31,12 +31,12 @@ devDependencies: packages: - /@multiplechain/types@0.1.55: - resolution: {integrity: sha512-9fYrLaDxX2pj9zfIbmvk1hPF3FH/bK+Q3uTF+k3zdsitP/HzQ1S9zImNz20Tvoqkk1ns+/8ecE0Y6GNowsDOQA==} + /@multiplechain/types@0.1.56: + resolution: {integrity: sha512-tnkgDwW0AWxEfhE/392LR6ZPE7Pxz5/Ei1XYsQISGkOfYYZrsvJXr69fXTjDOHCq7RCuQqytKmhnKs5K4xHd7w==} dev: false - /@multiplechain/utils@0.1.18: - resolution: {integrity: sha512-UCoOOBJrawp/lInepxuoEiYwId0wMPg7rX8p78FLqzGl8f/b93sAtv7sP87/VVKwhdoEuNZ/uQjckycmNeks/w==} + /@multiplechain/utils@0.1.20: + resolution: {integrity: sha512-4eEs4YR/V4F2Qnkl5KTZvPpewRQiX7C193d0tjpQuIfyumTEBJtdHYm1CW9CoJ6EjQUaB0oqSRKXomhzfK1qkw==} dependencies: '@types/ws': 8.5.10 bignumber.js: 9.1.2 diff --git a/packages/networks/bitcoin/src/models/Transaction.ts b/packages/networks/bitcoin/src/models/Transaction.ts index f99ffb8..4cdeed8 100644 --- a/packages/networks/bitcoin/src/models/Transaction.ts +++ b/packages/networks/bitcoin/src/models/Transaction.ts @@ -93,7 +93,7 @@ export class Transaction implements TransactionInterface { // Returns empty data when the transaction is first created. For this reason, it would be better to check it intermittently and give an error if it still does not exist. Average 10 seconds. if (String(axiosError?.response?.data).includes('Transaction not found')) { if (counter > 5) { - throw new Error('Transaction not found') + throw new Error(ErrorTypeEnum.TRANSACTION_NOT_FOUND) } counter++ await sleep(2000) diff --git a/packages/networks/bitcoin/src/services/TransactionListener.ts b/packages/networks/bitcoin/src/services/TransactionListener.ts index e535df5..04fa972 100644 --- a/packages/networks/bitcoin/src/services/TransactionListener.ts +++ b/packages/networks/bitcoin/src/services/TransactionListener.ts @@ -2,16 +2,18 @@ import type { TransactionTypeEnum, DynamicTransactionType, TransactionListenerInterface, - TransactionListenerCallbackType, DynamicTransactionListenerFilterType } from '@multiplechain/types' import WebSocket from 'ws' import { Provider } from './Provider.ts' -import { TransactionListenerProcessIndex } from '@multiplechain/types' -import { checkWebSocket, objectsEqual } from '@multiplechain/utils' -import { CoinTransaction } from '../models/CoinTransaction.ts' -import { Transaction } from '../models/Transaction.ts' import { fromSatoshi } from '../utils.ts' +import { Transaction } from '../models/Transaction.ts' +import type { NftTransaction } from '../models/NftTransaction.ts' +import { CoinTransaction } from '../models/CoinTransaction.ts' +import type { TokenTransaction } from '../models/TokenTransaction.ts' +import type { ContractTransaction } from '../models/ContractTransaction.ts' +import { checkWebSocket, objectsEqual } from '@multiplechain/utils' +import { TransactionListenerProcessIndex } from '@multiplechain/types' interface Values { txId: string @@ -20,8 +22,25 @@ interface Values { receiver?: string } -export class TransactionListener - implements TransactionListenerInterface +type TransactionListenerTriggerType = DynamicTransactionType< + T, + Transaction, + ContractTransaction, + CoinTransaction, + TokenTransaction, + NftTransaction +> + +type TransactionListenerCallbackType< + T extends TransactionTypeEnum, + Transaction = TransactionListenerTriggerType +> = (transaction: Transaction) => void + +export class TransactionListener< + T extends TransactionTypeEnum, + DTransaction extends TransactionListenerTriggerType, + CallBackType extends TransactionListenerCallbackType +> implements TransactionListenerInterface { /** * Transaction type @@ -31,7 +50,7 @@ export class TransactionListener /** * Transaction listener callback */ - callbacks: TransactionListenerCallbackType[] = [] + callbacks: CallBackType[] = [] /** * Transaction listener filter @@ -107,10 +126,10 @@ export class TransactionListener /** * Listen to the transaction events - * @param {TransactionListenerCallbackType} callback - Transaction listener callback + * @param {CallBackType} callback - Transaction listener callback * @returns {Promise} */ - async on(callback: TransactionListenerCallbackType): Promise { + async on(callback: CallBackType): Promise { if (this.webSocket === undefined) { try { await checkWebSocket(this.provider.wsUrl) @@ -131,14 +150,14 @@ export class TransactionListener /** * Trigger the event when a transaction is detected - * @param {DynamicTransactionType} transaction - Transaction data + * @param {TransactionListenerTriggerType} transaction - Transaction data * @returns {void} */ - trigger(transaction: DynamicTransactionType): void { + trigger(transaction: TransactionListenerTriggerType): void { if (!this.triggeredTransactions.includes(transaction.id)) { this.triggeredTransactions.push(transaction.id) this.callbacks.forEach((callback) => { - callback(transaction) + callback(transaction as unknown as DTransaction) }) } } From 982c46de5af2fd083148f276a07d1c8d1dc4085b Mon Sep 17 00:00:00 2001 From: Halil Beycan <50718965+BeycanDeveloper@users.noreply.github.com> Date: Tue, 21 May 2024 15:30:56 +0800 Subject: [PATCH 73/90] updated for new types --- packages/networks/evm-chains/package.json | 6 +-- packages/networks/evm-chains/pnpm-lock.yaml | 16 +++---- .../src/browser/adapters/WalletConnect.ts | 8 ++-- .../src/browser/adapters/Web3Modal.ts | 8 ++-- .../evm-chains/src/services/Ethers.ts | 3 +- .../src/services/TransactionListener.ts | 42 +++++++++++++------ 6 files changed, 50 insertions(+), 33 deletions(-) diff --git a/packages/networks/evm-chains/package.json b/packages/networks/evm-chains/package.json index ff6c410..af19dc8 100644 --- a/packages/networks/evm-chains/package.json +++ b/packages/networks/evm-chains/package.json @@ -1,6 +1,6 @@ { "name": "@multiplechain/evm-chains", - "version": "0.3.46", + "version": "0.4.0", "type": "module", "main": "dist/index.cjs", "module": "dist/index.es.js", @@ -65,8 +65,8 @@ "url": "https://github.com/MultipleChain/js/issues" }, "dependencies": { - "@multiplechain/types": "^0.1.55", - "@multiplechain/utils": "^0.1.18", + "@multiplechain/types": "^0.1.56", + "@multiplechain/utils": "^0.1.20", "@wagmi/chains": "^1.8.0", "@walletconnect/ethereum-provider": "^2.12.2", "@walletconnect/modal": "^2.6.2", diff --git a/packages/networks/evm-chains/pnpm-lock.yaml b/packages/networks/evm-chains/pnpm-lock.yaml index 8412711..6d97d08 100644 --- a/packages/networks/evm-chains/pnpm-lock.yaml +++ b/packages/networks/evm-chains/pnpm-lock.yaml @@ -6,11 +6,11 @@ settings: dependencies: '@multiplechain/types': - specifier: ^0.1.55 - version: 0.1.55 + specifier: ^0.1.56 + version: 0.1.56 '@multiplechain/utils': - specifier: ^0.1.18 - version: 0.1.18 + specifier: ^0.1.20 + version: 0.1.20 '@wagmi/chains': specifier: ^1.8.0 version: 1.8.0 @@ -239,12 +239,12 @@ packages: tslib: 2.4.0 dev: false - /@multiplechain/types@0.1.55: - resolution: {integrity: sha512-9fYrLaDxX2pj9zfIbmvk1hPF3FH/bK+Q3uTF+k3zdsitP/HzQ1S9zImNz20Tvoqkk1ns+/8ecE0Y6GNowsDOQA==} + /@multiplechain/types@0.1.56: + resolution: {integrity: sha512-tnkgDwW0AWxEfhE/392LR6ZPE7Pxz5/Ei1XYsQISGkOfYYZrsvJXr69fXTjDOHCq7RCuQqytKmhnKs5K4xHd7w==} dev: false - /@multiplechain/utils@0.1.18: - resolution: {integrity: sha512-UCoOOBJrawp/lInepxuoEiYwId0wMPg7rX8p78FLqzGl8f/b93sAtv7sP87/VVKwhdoEuNZ/uQjckycmNeks/w==} + /@multiplechain/utils@0.1.20: + resolution: {integrity: sha512-4eEs4YR/V4F2Qnkl5KTZvPpewRQiX7C193d0tjpQuIfyumTEBJtdHYm1CW9CoJ6EjQUaB0oqSRKXomhzfK1qkw==} dependencies: '@types/ws': 8.5.10 bignumber.js: 9.1.2 diff --git a/packages/networks/evm-chains/src/browser/adapters/WalletConnect.ts b/packages/networks/evm-chains/src/browser/adapters/WalletConnect.ts index 97f5708..8989a09 100644 --- a/packages/networks/evm-chains/src/browser/adapters/WalletConnect.ts +++ b/packages/networks/evm-chains/src/browser/adapters/WalletConnect.ts @@ -1,6 +1,6 @@ import icons from './icons.ts' import type { EIP1193Provider } from './EIP6963.ts' -import { WalletPlatformEnum } from '@multiplechain/types' +import { ErrorTypeEnum, WalletPlatformEnum } from '@multiplechain/types' import { EthereumProvider } from '@walletconnect/ethereum-provider' import type { EvmNetworkConfigInterface } from '../../services/Provider.ts' import type { @@ -29,15 +29,15 @@ const WalletConnect: WalletAdapterInterface = { const ops = _ops as WalletConnectOps if (provider === undefined) { - throw new Error('Provider is required') + throw new Error(ErrorTypeEnum.PROVIDER_IS_REQUIRED) } if (ops === undefined) { - throw new Error('Ops is required') + throw new Error(ErrorTypeEnum.OPS_IS_REQUIRED) } if (ops.projectId === undefined) { - throw new Error('Project ID is required') + throw new Error(ErrorTypeEnum.PROJECT_ID_IS_REQUIRED) } const rpcIdMapping = {} diff --git a/packages/networks/evm-chains/src/browser/adapters/Web3Modal.ts b/packages/networks/evm-chains/src/browser/adapters/Web3Modal.ts index f679a16..f0ac810 100644 --- a/packages/networks/evm-chains/src/browser/adapters/Web3Modal.ts +++ b/packages/networks/evm-chains/src/browser/adapters/Web3Modal.ts @@ -133,19 +133,19 @@ const Web3Modal: Web3ModalAdapterInterface = { const ops = _ops as Web3ModalOps if (provider === undefined) { - throw new Error('Provider is required') + throw new Error(ErrorTypeEnum.PROVIDER_IS_REQUIRED) } if (ops === undefined) { - throw new Error('Ops is required') + throw new Error(ErrorTypeEnum.OPS_IS_REQUIRED) } if (ops.projectId === undefined) { - throw new Error('Project ID is required') + throw new Error(ErrorTypeEnum.PROJECT_ID_IS_REQUIRED) } if (ops.metadata === undefined) { - throw new Error('Metadata is required') + throw new Error(ErrorTypeEnum.METADATA_IS_REQUIRED) } const network = provider.network as EvmNetworkConfigInterface diff --git a/packages/networks/evm-chains/src/services/Ethers.ts b/packages/networks/evm-chains/src/services/Ethers.ts index 7012397..55070c0 100644 --- a/packages/networks/evm-chains/src/services/Ethers.ts +++ b/packages/networks/evm-chains/src/services/Ethers.ts @@ -7,6 +7,7 @@ import type { TransactionReceipt, TransactionResponse } from 'ethers' +import { ErrorTypeEnum } from '@multiplechain/types' import { sleep, checkWebSocket } from '@multiplechain/utils' import type { EvmNetworkConfigInterface } from './Provider.ts' import type { TransactionData } from '../services/TransactionSigner.ts' @@ -58,7 +59,7 @@ export class Ethers { public async connectWebSocket(): Promise { return await new Promise((resolve, reject) => { if (this.network.wsUrl === undefined) { - reject(new Error('WebSocket URL is not defined')) + reject(new Error(ErrorTypeEnum.WS_URL_NOT_DEFINED)) } else { const url = this.network.wsUrl checkWebSocket(url) diff --git a/packages/networks/evm-chains/src/services/TransactionListener.ts b/packages/networks/evm-chains/src/services/TransactionListener.ts index 822b275..ec9561e 100644 --- a/packages/networks/evm-chains/src/services/TransactionListener.ts +++ b/packages/networks/evm-chains/src/services/TransactionListener.ts @@ -2,7 +2,6 @@ import type { TransactionTypeEnum, DynamicTransactionType, TransactionListenerInterface, - TransactionListenerCallbackType, DynamicTransactionListenerFilterType } from '@multiplechain/types' @@ -14,7 +13,7 @@ import { Transaction } from '../models/Transaction.ts' import { NftTransaction } from '../models/NftTransaction.ts' import { CoinTransaction } from '../models/CoinTransaction.ts' import { TokenTransaction } from '../models/TokenTransaction.ts' -import { TransactionListenerProcessIndex } from '@multiplechain/types' +import { ErrorTypeEnum, TransactionListenerProcessIndex } from '@multiplechain/types' import { ContractTransaction } from '../models/ContractTransaction.ts' import { type WebSocketProvider, @@ -24,8 +23,25 @@ import { type TransactionResponse } from 'ethers' -export class TransactionListener - implements TransactionListenerInterface +type TransactionListenerTriggerType = DynamicTransactionType< + T, + Transaction, + ContractTransaction, + CoinTransaction, + TokenTransaction, + NftTransaction +> + +type TransactionListenerCallbackType< + T extends TransactionTypeEnum, + Transaction = TransactionListenerTriggerType +> = (transaction: Transaction) => void + +export class TransactionListener< + T extends TransactionTypeEnum, + DTransaction extends TransactionListenerTriggerType, + CallBackType extends TransactionListenerCallbackType +> implements TransactionListenerInterface { /** * Transaction type @@ -35,7 +51,7 @@ export class TransactionListener /** * Transaction listener callback */ - callbacks: TransactionListenerCallbackType[] = [] + callbacks: CallBackType[] = [] /** * Transaction listener filter @@ -123,14 +139,14 @@ export class TransactionListener /** * Listen to the transaction events - * @param {TransactionListenerCallbackType} callback - Callback function + * @param {CallBackType} callback - Callback function * @returns {Promise} */ - async on(callback: TransactionListenerCallbackType): Promise { + async on(callback: CallBackType): Promise { if (this.webSocket === undefined) { const socket = await this.provider.ethers.connectWebSocket() if (typeof socket === 'string') { - throw new Error('WebSocket connection is not available') + throw new Error(ErrorTypeEnum.WS_CONNECTION_FAILED) } else { this.webSocket = socket } @@ -144,15 +160,15 @@ export class TransactionListener /** * Trigger the event when a transaction is detected - * @param {DynamicTransactionType} transaction - Transaction data + * @param {TransactionListenerTriggerType} transaction - Transaction data * @returns {void} */ - trigger(transaction: DynamicTransactionType): void { + trigger(transaction: TransactionListenerTriggerType): void { if (!this.triggeredTransactions.includes(transaction.id)) { this.triggeredTransactions.push(transaction.id) - for (const callback of this.callbacks) { - callback(transaction) - } + this.callbacks.forEach((callback) => { + callback(transaction as unknown as DTransaction) + }) } } From 8e8b7258571cd9131825f8ec4f6c32282f42d8cb Mon Sep 17 00:00:00 2001 From: Halil Beycan <50718965+BeycanDeveloper@users.noreply.github.com> Date: Tue, 21 May 2024 15:36:40 +0800 Subject: [PATCH 74/90] updated for new types --- packages/networks/tron/package.json | 6 +-- packages/networks/tron/pnpm-lock.yaml | 21 ++++++---- .../src/browser/adapters/WalletConnect.ts | 8 ++-- .../tron/src/services/TransactionListener.ts | 41 +++++++++++++++---- 4 files changed, 52 insertions(+), 24 deletions(-) diff --git a/packages/networks/tron/package.json b/packages/networks/tron/package.json index 0a1b294..6b4cce9 100644 --- a/packages/networks/tron/package.json +++ b/packages/networks/tron/package.json @@ -1,6 +1,6 @@ { "name": "@multiplechain/tron", - "version": "0.2.11", + "version": "0.4.0", "type": "module", "main": "dist/index.cjs", "module": "dist/index.es.js", @@ -64,8 +64,8 @@ "dependencies": { "@beycandeveloper/tron-tx-decoder": "^2.0.5", "@multiplechain/tron-walletconnect": "^0.1.0", - "@multiplechain/types": "^0.1.55", - "@multiplechain/utils": "^0.1.18", + "@multiplechain/types": "^0.1.56", + "@multiplechain/utils": "^0.1.20", "@noble/secp256k1": "^1.7.1", "@tronweb3/tronwallet-adapter-bitkeep": "^1.1.1", "@tronweb3/tronwallet-adapter-okxwallet": "^1.0.3", diff --git a/packages/networks/tron/pnpm-lock.yaml b/packages/networks/tron/pnpm-lock.yaml index 7dc6724..9245368 100644 --- a/packages/networks/tron/pnpm-lock.yaml +++ b/packages/networks/tron/pnpm-lock.yaml @@ -12,11 +12,11 @@ dependencies: specifier: ^0.1.0 version: 0.1.0(typescript@5.4.5) '@multiplechain/types': - specifier: ^0.1.55 - version: 0.1.55 + specifier: ^0.1.56 + version: 0.1.56 '@multiplechain/utils': - specifier: ^0.1.18 - version: 0.1.18 + specifier: ^0.1.20 + version: 0.1.20 '@noble/secp256k1': specifier: ^1.7.1 version: 1.7.1 @@ -348,12 +348,12 @@ packages: - vite dev: false - /@multiplechain/types@0.1.55: - resolution: {integrity: sha512-9fYrLaDxX2pj9zfIbmvk1hPF3FH/bK+Q3uTF+k3zdsitP/HzQ1S9zImNz20Tvoqkk1ns+/8ecE0Y6GNowsDOQA==} + /@multiplechain/types@0.1.56: + resolution: {integrity: sha512-tnkgDwW0AWxEfhE/392LR6ZPE7Pxz5/Ei1XYsQISGkOfYYZrsvJXr69fXTjDOHCq7RCuQqytKmhnKs5K4xHd7w==} dev: false - /@multiplechain/utils@0.1.18: - resolution: {integrity: sha512-UCoOOBJrawp/lInepxuoEiYwId0wMPg7rX8p78FLqzGl8f/b93sAtv7sP87/VVKwhdoEuNZ/uQjckycmNeks/w==} + /@multiplechain/utils@0.1.20: + resolution: {integrity: sha512-4eEs4YR/V4F2Qnkl5KTZvPpewRQiX7C193d0tjpQuIfyumTEBJtdHYm1CW9CoJ6EjQUaB0oqSRKXomhzfK1qkw==} dependencies: '@types/ws': 8.5.10 bignumber.js: 9.1.2 @@ -488,6 +488,7 @@ packages: dependencies: is-glob: 4.0.3 micromatch: 4.0.5 + napi-wasm: 1.1.0 dev: false bundledDependencies: - napi-wasm @@ -2331,6 +2332,10 @@ packages: resolution: {integrity: sha512-HoMUjhH9T8DDBNT+6xzkrd9ga/XiBI4xLr58LJACwK6G3HTOPeMz4nB4KJs33L2BelrIJa7P0VuNaVF3hMYfjg==} dev: false + /napi-wasm@1.1.0: + resolution: {integrity: sha512-lHwIAJbmLSjF9VDRm9GoVOy9AGp3aIvkjv+Kvz9h16QR3uSVYH78PNQUnT2U4X53mhlnV2M7wrhibQ3GHicDmg==} + dev: false + /node-addon-api@7.1.0: resolution: {integrity: sha512-mNcltoe1R8o7STTegSOHdnJNN7s5EUvhoS7ShnTHDyOSd+8H+UdWODq6qSv67PjC8Zc5JRT8+oLAMCr0SIXw7g==} engines: {node: ^16 || ^18 || >= 20} diff --git a/packages/networks/tron/src/browser/adapters/WalletConnect.ts b/packages/networks/tron/src/browser/adapters/WalletConnect.ts index 2766b2f..5f95416 100644 --- a/packages/networks/tron/src/browser/adapters/WalletConnect.ts +++ b/packages/networks/tron/src/browser/adapters/WalletConnect.ts @@ -1,5 +1,5 @@ import type { CustomAdapter } from '../Wallet.ts' -import { WalletPlatformEnum } from '@multiplechain/types' +import { ErrorTypeEnum, WalletPlatformEnum } from '@multiplechain/types' import { WalletConnectAdapter } from '@multiplechain/tron-walletconnect' import type { ProviderInterface, @@ -50,15 +50,15 @@ const WalletConnect: WalletAdapterInterface = { const ops = _ops as WalletConnectOps if (provider === undefined) { - throw new Error('Provider is required') + throw new Error(ErrorTypeEnum.PROVIDER_IS_REQUIRED) } if (ops === undefined) { - throw new Error('Ops is required') + throw new Error(ErrorTypeEnum.OPS_IS_REQUIRED) } if (ops.projectId === undefined) { - throw new Error('Project ID is required') + throw new Error(ErrorTypeEnum.PROJECT_ID_IS_REQUIRED) } const walletProvider = new WalletConnectAdapter({ diff --git a/packages/networks/tron/src/services/TransactionListener.ts b/packages/networks/tron/src/services/TransactionListener.ts index 6ee6505..cb57c69 100644 --- a/packages/networks/tron/src/services/TransactionListener.ts +++ b/packages/networks/tron/src/services/TransactionListener.ts @@ -2,15 +2,38 @@ import type { TransactionTypeEnum, DynamicTransactionType, TransactionListenerInterface, - TransactionListenerCallbackType, DynamicTransactionListenerFilterType } from '@multiplechain/types' import { Provider } from './Provider.ts' +import type { + Transaction, + TokenTransaction, + CoinTransaction, + ContractTransaction, + NftTransaction +} from '../models/index.ts' import { TransactionListenerProcessIndex } from '@multiplechain/types' -export class TransactionListener - implements TransactionListenerInterface +type TransactionListenerTriggerType = DynamicTransactionType< + T, + Transaction, + ContractTransaction, + CoinTransaction, + TokenTransaction, + NftTransaction +> + +type TransactionListenerCallbackType< + T extends TransactionTypeEnum, + Transaction = TransactionListenerTriggerType +> = (transaction: Transaction) => void + +export class TransactionListener< + T extends TransactionTypeEnum, + DTransaction extends TransactionListenerTriggerType, + CallBackType extends TransactionListenerCallbackType +> implements TransactionListenerInterface { /** * Transaction type @@ -20,7 +43,7 @@ export class TransactionListener /** * Transaction listener callback */ - callbacks: TransactionListenerCallbackType[] = [] + callbacks: CallBackType[] = [] /** * Transaction listener filter @@ -92,10 +115,10 @@ export class TransactionListener /** * Listen to the transaction events - * @param {TransactionListenerCallbackType} callback - Transaction listener callback + * @param {CallBackType} callback - Transaction listener callback * @returns {Promise} */ - async on(callback: TransactionListenerCallbackType): Promise { + async on(callback: CallBackType): Promise { this.start() this.callbacks.push(callback) return true @@ -103,14 +126,14 @@ export class TransactionListener /** * Trigger the event when a transaction is detected - * @param {DynamicTransactionType} transaction - Transaction data + * @param {TransactionListenerTriggerType} transaction - Transaction data * @returns {void} */ - trigger(transaction: DynamicTransactionType): void { + trigger(transaction: TransactionListenerTriggerType): void { if (!this.triggeredTransactions.includes(transaction.id)) { this.triggeredTransactions.push(transaction.id) this.callbacks.forEach((callback) => { - callback(transaction) + callback(transaction as unknown as DTransaction) }) } } From 29b81fecc727a510c79688ccf25923bf324f7346 Mon Sep 17 00:00:00 2001 From: Halil Beycan <50718965+BeycanDeveloper@users.noreply.github.com> Date: Tue, 21 May 2024 16:26:54 +0800 Subject: [PATCH 75/90] updated --- packages/networks/bitcoin/index.html | 4 ++++ packages/networks/boilerplate/index.html | 4 ++++ packages/networks/evm-chains/index.html | 4 ++++ packages/networks/solana/index.html | 6 +++++- 4 files changed, 17 insertions(+), 1 deletion(-) diff --git a/packages/networks/bitcoin/index.html b/packages/networks/bitcoin/index.html index c650b2f..2324a82 100644 --- a/packages/networks/bitcoin/index.html +++ b/packages/networks/bitcoin/index.html @@ -215,6 +215,10 @@ window.adapters = {} window.connectAdapter = async (adapter) => { + if (await adapter.isDetected() === false) { + return alert('Adapter is not detected') + } + if (adapter.disconnect) { await adapter.disconnect() } diff --git a/packages/networks/boilerplate/index.html b/packages/networks/boilerplate/index.html index 4c31e53..05e89cf 100644 --- a/packages/networks/boilerplate/index.html +++ b/packages/networks/boilerplate/index.html @@ -224,6 +224,10 @@ window.adapters = {} window.connectAdapter = async (adapter) => { + if (await adapter.isDetected() === false) { + return alert('Adapter is not detected') + } + if (adapter.disconnect) { await adapter.disconnect() } diff --git a/packages/networks/evm-chains/index.html b/packages/networks/evm-chains/index.html index 5a2933b..64b37ec 100644 --- a/packages/networks/evm-chains/index.html +++ b/packages/networks/evm-chains/index.html @@ -235,6 +235,10 @@ window.adapters = {} window.connectAdapter = async (adapter) => { + if (await adapter.isDetected() === false) { + return alert('Adapter is not detected') + } + if (adapter.disconnect) { await adapter.disconnect() } diff --git a/packages/networks/solana/index.html b/packages/networks/solana/index.html index d7851b1..1b151a6 100644 --- a/packages/networks/solana/index.html +++ b/packages/networks/solana/index.html @@ -219,11 +219,15 @@ window.Solana = Solana const provider = new Solana.Provider({ - // options + testnet: true, }); window.adapters = {} window.connectAdapter = async (adapter) => { + if (await adapter.isDetected() === false) { + return alert('Adapter is not detected') + } + if (adapter.disconnect) { await adapter.disconnect() } From d37eb953ef96398b8efc16df0cf05d1314754ab6 Mon Sep 17 00:00:00 2001 From: Halil Beycan <50718965+BeycanDeveloper@users.noreply.github.com> Date: Tue, 21 May 2024 16:57:45 +0800 Subject: [PATCH 76/90] updated --- packages/networks/boilerplate/index.html | 4 ---- 1 file changed, 4 deletions(-) diff --git a/packages/networks/boilerplate/index.html b/packages/networks/boilerplate/index.html index 05e89cf..4e508e4 100644 --- a/packages/networks/boilerplate/index.html +++ b/packages/networks/boilerplate/index.html @@ -187,9 +187,6 @@
Deep link:
-
- Chain id: -
Connected address:
@@ -246,7 +243,6 @@ document.querySelector('.platforms').innerText = wallet.getPlatforms().join(', ') document.querySelector('.download-link').innerText = wallet.getDownloadLink() document.querySelector('.deep-link').innerText = wallet.createDeepLink('https://google.com') - document.querySelector('.chain-id').innerText = await wallet.getChainId() document.querySelector('.connected-address').innerText = sender document.querySelector('.action-result .sign-message').innerText = '' From 162d3cce7dfdafce81f87335efd2a5d38c73caac Mon Sep 17 00:00:00 2001 From: Halil Beycan <50718965+BeycanDeveloper@users.noreply.github.com> Date: Tue, 21 May 2024 17:28:31 +0800 Subject: [PATCH 77/90] completed wallet and phantom adapter --- packages/networks/solana/index.html | 8 +- packages/networks/solana/package.json | 2 + packages/networks/solana/pnpm-lock.yaml | 49 +++++++ .../networks/solana/src/browser/Wallet.ts | 134 ++++++++++++++++-- .../solana/src/browser/adapters/Example.ts | 29 ---- .../solana/src/browser/adapters/Phantom.ts | 44 ++++++ .../solana/src/browser/adapters/index.ts | 2 +- 7 files changed, 219 insertions(+), 49 deletions(-) delete mode 100644 packages/networks/solana/src/browser/adapters/Example.ts create mode 100644 packages/networks/solana/src/browser/adapters/Phantom.ts diff --git a/packages/networks/solana/index.html b/packages/networks/solana/index.html index 1b151a6..3727ef9 100644 --- a/packages/networks/solana/index.html +++ b/packages/networks/solana/index.html @@ -187,9 +187,6 @@
Deep link:
-
- Chain id: -
Connected address:
@@ -246,7 +243,6 @@ document.querySelector('.platforms').innerText = wallet.getPlatforms().join(', ') document.querySelector('.download-link').innerText = wallet.getDownloadLink() document.querySelector('.deep-link').innerText = wallet.createDeepLink('https://google.com') - document.querySelector('.chain-id').innerText = await wallet.getChainId() document.querySelector('.connected-address').innerText = sender document.querySelector('.action-result .sign-message').innerText = '' @@ -255,8 +251,8 @@ document.querySelector('.action-result .sign-message').innerText = result } - const receiver = '0xbBa4d06D1cEf94b35aDeCfDa893523907fdD36DE'; - const tokenAddress = '0x4294cb0dD25dC9140B5127f247cBd47Eeb673431'; + const receiver = 'GHVMV3zZscR8V4K5GEgQTUjuV4jEixB9a4QX3KhgvVKy'; + const tokenAddress = '2ZHwL3dXk3szRgiBLZi244NmKs2VmoBx764AYMY2tQfx'; document.querySelector('.action-result .send-coin').innerText = '' document.querySelector('.action-btn.send-coin').onclick = async () => { diff --git a/packages/networks/solana/package.json b/packages/networks/solana/package.json index 4aa9409..ecc7789 100644 --- a/packages/networks/solana/package.json +++ b/packages/networks/solana/package.json @@ -67,6 +67,8 @@ "@multiplechain/utils": "^0.1.20", "@solana/spl-token": "^0.4.6", "@solana/spl-token-metadata": "^0.1.4", + "@solana/wallet-adapter-base": "^0.9.23", + "@solana/wallet-adapter-phantom": "^0.9.24", "@solana/web3.js": "^1.91.8", "axios": "^1.6.8" } diff --git a/packages/networks/solana/pnpm-lock.yaml b/packages/networks/solana/pnpm-lock.yaml index eeb2be6..7b56bb5 100644 --- a/packages/networks/solana/pnpm-lock.yaml +++ b/packages/networks/solana/pnpm-lock.yaml @@ -20,6 +20,12 @@ dependencies: '@solana/spl-token-metadata': specifier: ^0.1.4 version: 0.1.4(@solana/web3.js@1.91.8)(fastestsmallesttextencoderdecoder@1.0.22) + '@solana/wallet-adapter-base': + specifier: ^0.9.23 + version: 0.9.23(@solana/web3.js@1.91.8) + '@solana/wallet-adapter-phantom': + specifier: ^0.9.24 + version: 0.9.24(@solana/web3.js@1.91.8) '@solana/web3.js': specifier: ^1.91.8 version: 1.91.8 @@ -1016,6 +1022,37 @@ packages: buffer: 6.0.3 dev: false + /@solana/wallet-adapter-base@0.9.23(@solana/web3.js@1.91.8): + resolution: {integrity: sha512-apqMuYwFp1jFi55NxDfvXUX2x1T0Zh07MxhZ/nCCTGys5raSfYUh82zen2BLv8BSDj/JxZ2P/s7jrQZGrX8uAw==} + engines: {node: '>=16'} + peerDependencies: + '@solana/web3.js': ^1.77.3 + dependencies: + '@solana/wallet-standard-features': 1.2.0 + '@solana/web3.js': 1.91.8 + '@wallet-standard/base': 1.0.1 + '@wallet-standard/features': 1.0.3 + eventemitter3: 4.0.7 + dev: false + + /@solana/wallet-adapter-phantom@0.9.24(@solana/web3.js@1.91.8): + resolution: {integrity: sha512-D24AxRHmRJ4AYoRvijbiuUb9LmC4xLGKLMSJS2ly+zGxVmaPASPM/ThaY/DlYTDL31QvkYtl8RzSR4yIU1gpLg==} + engines: {node: '>=16'} + peerDependencies: + '@solana/web3.js': ^1.77.3 + dependencies: + '@solana/wallet-adapter-base': 0.9.23(@solana/web3.js@1.91.8) + '@solana/web3.js': 1.91.8 + dev: false + + /@solana/wallet-standard-features@1.2.0: + resolution: {integrity: sha512-tUd9srDLkRpe1BYg7we+c4UhRQkq+XQWswsr/L1xfGmoRDF47BPSXf4zE7ZU2GRBGvxtGt7lwJVAufQyQYhxTQ==} + engines: {node: '>=16'} + dependencies: + '@wallet-standard/base': 1.0.1 + '@wallet-standard/features': 1.0.3 + dev: false + /@solana/web3.js@1.91.8: resolution: {integrity: sha512-USa6OS1jbh8zOapRJ/CBZImZ8Xb7AJjROZl5adql9TpOoBN9BUzyyouS5oPuZHft7S7eB8uJPuXWYjMi6BHgOw==} dependencies: @@ -1077,6 +1114,18 @@ packages: '@types/node': 20.12.7 dev: false + /@wallet-standard/base@1.0.1: + resolution: {integrity: sha512-1To3ekMfzhYxe0Yhkpri+Fedq0SYcfrOfJi3vbLjMwF2qiKPjTGLwZkf2C9ftdQmxES+hmxhBzTwF4KgcOwf8w==} + engines: {node: '>=16'} + dev: false + + /@wallet-standard/features@1.0.3: + resolution: {integrity: sha512-m8475I6W5LTatTZuUz5JJNK42wFRgkJTB0I9tkruMwfqBF2UN2eomkYNVf9RbrsROelCRzSFmugqjKZBFaubsA==} + engines: {node: '>=16'} + dependencies: + '@wallet-standard/base': 1.0.1 + dev: false + /JSONStream@1.3.5: resolution: {integrity: sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==} hasBin: true diff --git a/packages/networks/solana/src/browser/Wallet.ts b/packages/networks/solana/src/browser/Wallet.ts index 83ade3f..9f60a5b 100644 --- a/packages/networks/solana/src/browser/Wallet.ts +++ b/packages/networks/solana/src/browser/Wallet.ts @@ -1,19 +1,84 @@ -import type { - WalletInterface, - WalletAdapterInterface, - WalletPlatformEnum, - TransactionSignerInterface, - ProviderInterface +import { + type WalletInterface, + type WalletAdapterInterface, + type WalletPlatformEnum, + type TransactionSignerInterface, + type ProviderInterface, + ErrorTypeEnum } from '@multiplechain/types' import { Provider } from '../services/Provider.ts' +import type { + BaseMessageSignerWalletAdapter, + WalletAdapterEvents +} from '@solana/wallet-adapter-base' +import { base58Encode } from '@multiplechain/utils' + +const rejectMap = (error: any, reject: (a: any) => any): any => { + console.error('MultipleChain Solana Wallet Error:', error) + + const errorMessage = String(error.message ?? '') + + if (typeof error === 'object') { + if (errorMessage.includes('QR Code Modal Closed')) { + return reject(new Error(ErrorTypeEnum.CLOSED_WALLETCONNECT_MODAL)) + } + + if (error.name === 'WalletSendTransactionError') { + if ( + errorMessage.includes('Unexpected error') || + errorMessage.includes('Transaction simulation failed: Blockhash not found') || + errorMessage.includes( + 'Transaction results in an account (1) without insufficient funds for rent' + ) + ) { + return reject(error) + } + } + + if ( + [ + 'WalletConnectionError', + 'WalletWindowClosedError', + 'WalletAccountError', + 'WalletSendTransactionError' + ].includes(String(error.name)) || + error.code === 4001 || + errorMessage === 'User rejected the request.' || + error.name === 'WalletSignTransactionError' || + errorMessage.includes('user reject this request') || + errorMessage === 'User canceled request' + ) { + return reject(new Error(ErrorTypeEnum.WALLET_REQUEST_REJECTED)) + } else if (error.name === 'WalletTimeoutError') { + return reject(new Error(ErrorTypeEnum.WALLET_CONNECTION_TIMEOUT)) + } else if ( + (errorMessage.length > 0 && errorMessage.includes('403')) || + (errorMessage.length > 0 && errorMessage.includes('Access forbidden')) + ) { + return reject(new Error(ErrorTypeEnum.RPC_ACCESS_DENIED)) + } else if (error.name === 'WalletNotReadyError') { + return reject(new Error(ErrorTypeEnum.WALLET_CONNECTION_FAILED)) + } else if ( + (error.name === 'WalletSendTransactionError' && + errorMessage !== 'User rejected the request') || + errorMessage === 'User disapproved requested chains' + ) { + return reject(new Error(ErrorTypeEnum.UNACCEPTED_CHAIN)) + } + } + + return reject(error) +} export class Wallet implements WalletInterface { adapter: WalletAdapterInterface - walletProvider: object + walletProvider: BaseMessageSignerWalletAdapter networkProvider: Provider + currentReject: (a: any) => any + /** * @param {WalletAdapterInterface} adapter * @param {Provider} provider @@ -77,8 +142,26 @@ export class Wallet implements WalletInterface { * @returns {Promise} */ async connect(provider?: ProviderInterface, ops?: object): Promise { - await this.adapter.connect() - return 'wallet address' + return await new Promise((resolve, reject) => { + this.currentReject = reject + this.adapter + .connect(provider, ops) + .then(async (provider) => { + this.walletProvider = provider as BaseMessageSignerWalletAdapter + this.on('error', (error) => rejectMap(error, this.currentReject)) + resolve(await this.getAddress()) + }) + .catch((error) => { + const customReject = (error: any): void => { + if (error.message === ErrorTypeEnum.WALLET_REQUEST_REJECTED) { + reject(new Error(ErrorTypeEnum.WALLET_CONNECT_REJECTED)) + } else { + reject(error) + } + } + rejectMap(error, customReject) + }) + }) } /** @@ -99,14 +182,24 @@ export class Wallet implements WalletInterface { * @returns {Promise} */ async getAddress(): Promise { - return 'wallet address' + return this.walletProvider.publicKey?.toBase58() ?? '' } /** * @param {string} message */ async signMessage(message: string): Promise { - return 'signed message' + return await new Promise((resolve, reject) => { + this.currentReject = reject + this.walletProvider + .signMessage(Buffer.from(message, 'utf8')) + .then((signature: Uint8Array) => { + resolve(base58Encode(signature)) + }) + .catch((error) => { + rejectMap(error, reject) + }) + }) } /** @@ -114,7 +207,22 @@ export class Wallet implements WalletInterface { * @returns {Promise} */ async sendTransaction(transactionSigner: TransactionSignerInterface): Promise { - return 'transaction hash' + return await new Promise((resolve, reject) => { + this.currentReject = reject + try { + void (async () => { + const recentBlockhash = ( + await this.networkProvider.web3.getLatestBlockhash('finalized') + ).blockhash + const tx = await this.walletProvider.signTransaction( + Object.assign(transactionSigner.getRawData(), { recentBlockhash }) + ) + resolve(base58Encode(tx.signature as Uint8Array)) + })() + } catch (error) { + rejectMap(error, reject) + } + }) } /** @@ -123,6 +231,6 @@ export class Wallet implements WalletInterface { * @returns {void} */ on(eventName: string, callback: (...args: any[]) => void): void { - 'wallet events' + this.walletProvider.on(eventName as keyof WalletAdapterEvents, callback) } } diff --git a/packages/networks/solana/src/browser/adapters/Example.ts b/packages/networks/solana/src/browser/adapters/Example.ts deleted file mode 100644 index b7390b3..0000000 --- a/packages/networks/solana/src/browser/adapters/Example.ts +++ /dev/null @@ -1,29 +0,0 @@ -import { WalletPlatformEnum } from '@multiplechain/types' -import type { WalletAdapterInterface } from '@multiplechain/types' - -declare global { - interface Window { - example: any - } -} - -const Example: WalletAdapterInterface = { - id: 'example', - name: 'Example', - icon: 'icon base64 string here', - platforms: [WalletPlatformEnum.BROWSER, WalletPlatformEnum.MOBILE], - downloadLink: 'wallet download link here', - createDeepLink(url: string, ops?: object): string { - return `https://example.com/dapp/${url}` - }, - isDetected: () => Boolean(window?.example), - isConnected: async () => { - return true // return true if connected - }, - connect: async () => { - // connect wallet here - return window.example - } -} - -export default Example diff --git a/packages/networks/solana/src/browser/adapters/Phantom.ts b/packages/networks/solana/src/browser/adapters/Phantom.ts new file mode 100644 index 0000000..c7e8a84 --- /dev/null +++ b/packages/networks/solana/src/browser/adapters/Phantom.ts @@ -0,0 +1,44 @@ +import { WalletPlatformEnum } from '@multiplechain/types' +import { PhantomWalletAdapter } from '@solana/wallet-adapter-phantom' +import type { BaseMessageSignerWalletAdapter } from '@solana/wallet-adapter-base' +import type { ProviderInterface, WalletAdapterInterface } from '@multiplechain/types' + +const phantomAdapter = new PhantomWalletAdapter() + +declare global { + interface Window { + phantom?: { + connect?: () => Promise + solana?: { + isPhantom?: boolean + } + } + } +} + +const Phantom: WalletAdapterInterface = { + id: 'phantom', + name: phantomAdapter.name, + icon: phantomAdapter.icon, + platforms: [WalletPlatformEnum.BROWSER, WalletPlatformEnum.MOBILE], + downloadLink: 'https://phantom.app/download', + createDeepLink(url: string, _ops?: object): string { + return `https://phantom.app/ul/browse/${url}?ref=${url}` + }, + isDetected: () => + Boolean( + window.phantom?.solana?.isPhantom !== undefined && window.phantom?.connect === undefined + ), + isConnected: async () => { + return true // return true if connected + }, + connect: async ( + _provider?: ProviderInterface, + _ops?: object + ): Promise => { + await phantomAdapter.connect() + return phantomAdapter + } +} + +export default Phantom diff --git a/packages/networks/solana/src/browser/adapters/index.ts b/packages/networks/solana/src/browser/adapters/index.ts index de0149d..2b7b60e 100644 --- a/packages/networks/solana/src/browser/adapters/index.ts +++ b/packages/networks/solana/src/browser/adapters/index.ts @@ -1 +1 @@ -export { default as Example } from './Example.ts' +export { default as Example } from './Phantom.ts' From a86e98468031a8b9d6a7a7910e5934e8a8765e13 Mon Sep 17 00:00:00 2001 From: Halil Beycan <50718965+BeycanDeveloper@users.noreply.github.com> Date: Tue, 21 May 2024 17:48:33 +0800 Subject: [PATCH 78/90] solflare completed --- packages/networks/solana/package.json | 1 + packages/networks/solana/pnpm-lock.yaml | 60 +++++++++++++++++++ .../networks/solana/src/browser/Wallet.ts | 19 +++--- .../solana/src/browser/adapters/Solflare.ts | 48 +++++++++++++++ .../solana/src/browser/adapters/index.ts | 3 +- 5 files changed, 122 insertions(+), 9 deletions(-) create mode 100644 packages/networks/solana/src/browser/adapters/Solflare.ts diff --git a/packages/networks/solana/package.json b/packages/networks/solana/package.json index ecc7789..aebf398 100644 --- a/packages/networks/solana/package.json +++ b/packages/networks/solana/package.json @@ -69,6 +69,7 @@ "@solana/spl-token-metadata": "^0.1.4", "@solana/wallet-adapter-base": "^0.9.23", "@solana/wallet-adapter-phantom": "^0.9.24", + "@solana/wallet-adapter-solflare": "^0.6.28", "@solana/web3.js": "^1.91.8", "axios": "^1.6.8" } diff --git a/packages/networks/solana/pnpm-lock.yaml b/packages/networks/solana/pnpm-lock.yaml index 7b56bb5..9aaeca5 100644 --- a/packages/networks/solana/pnpm-lock.yaml +++ b/packages/networks/solana/pnpm-lock.yaml @@ -26,6 +26,9 @@ dependencies: '@solana/wallet-adapter-phantom': specifier: ^0.9.24 version: 0.9.24(@solana/web3.js@1.91.8) + '@solana/wallet-adapter-solflare': + specifier: ^0.6.28 + version: 0.6.28(@solana/web3.js@1.91.8) '@solana/web3.js': specifier: ^1.91.8 version: 1.91.8 @@ -1045,6 +1048,27 @@ packages: '@solana/web3.js': 1.91.8 dev: false + /@solana/wallet-adapter-solflare@0.6.28(@solana/web3.js@1.91.8): + resolution: {integrity: sha512-iiUQtuXp8p4OdruDawsm1dRRnzUCcsu+lKo8OezESskHtbmZw2Ifej0P99AbJbBAcBw7q4GPI6987Vh05Si5rw==} + engines: {node: '>=16'} + peerDependencies: + '@solana/web3.js': ^1.77.3 + dependencies: + '@solana/wallet-adapter-base': 0.9.23(@solana/web3.js@1.91.8) + '@solana/wallet-standard-chains': 1.1.0 + '@solana/web3.js': 1.91.8 + '@solflare-wallet/metamask-sdk': 1.0.3(@solana/web3.js@1.91.8) + '@solflare-wallet/sdk': 1.4.2(@solana/web3.js@1.91.8) + '@wallet-standard/wallet': 1.0.1 + dev: false + + /@solana/wallet-standard-chains@1.1.0: + resolution: {integrity: sha512-IRJHf94UZM8AaRRmY18d34xCJiVPJej1XVwXiTjihHnmwD0cxdQbc/CKjrawyqFyQAKJx7raE5g9mnJsAdspTg==} + engines: {node: '>=16'} + dependencies: + '@wallet-standard/base': 1.0.1 + dev: false + /@solana/wallet-standard-features@1.2.0: resolution: {integrity: sha512-tUd9srDLkRpe1BYg7we+c4UhRQkq+XQWswsr/L1xfGmoRDF47BPSXf4zE7ZU2GRBGvxtGt7lwJVAufQyQYhxTQ==} engines: {node: '>=16'} @@ -1077,6 +1101,30 @@ packages: - utf-8-validate dev: false + /@solflare-wallet/metamask-sdk@1.0.3(@solana/web3.js@1.91.8): + resolution: {integrity: sha512-os5Px5PTMYKGS5tzOoyjDxtOtj0jZKnbI1Uwt8+Jsw1HHIA+Ib2UACCGNhQ/un2f8sIbTfLD1WuucNMOy8KZpQ==} + peerDependencies: + '@solana/web3.js': '*' + dependencies: + '@solana/wallet-standard-features': 1.2.0 + '@solana/web3.js': 1.91.8 + '@wallet-standard/base': 1.0.1 + bs58: 5.0.0 + eventemitter3: 5.0.1 + uuid: 9.0.1 + dev: false + + /@solflare-wallet/sdk@1.4.2(@solana/web3.js@1.91.8): + resolution: {integrity: sha512-jrseNWipwl9xXZgrzwZF3hhL0eIVxuEtoZOSLmuPuef7FgHjstuTtNJAeT4icA7pzdDV4hZvu54pI2r2f7SmrQ==} + peerDependencies: + '@solana/web3.js': '*' + dependencies: + '@solana/web3.js': 1.91.8 + bs58: 5.0.0 + eventemitter3: 5.0.1 + uuid: 9.0.1 + dev: false + /@supercharge/promise-pool@3.2.0: resolution: {integrity: sha512-pj0cAALblTZBPtMltWOlZTQSLT07jIaFNeM8TWoJD1cQMgDB9mcMlVMoetiB35OzNJpqQ2b+QEtwiR9f20mADg==} engines: {node: '>=8'} @@ -1126,6 +1174,13 @@ packages: '@wallet-standard/base': 1.0.1 dev: false + /@wallet-standard/wallet@1.0.1: + resolution: {integrity: sha512-qkhJeuQU2afQTZ02yMZE5SFc91Fo3hyFjFkpQglHudENNyiSG0oUKcIjky8X32xVSaumgTZSQUAzpXnCTWHzKQ==} + engines: {node: '>=16'} + dependencies: + '@wallet-standard/base': 1.0.1 + dev: false + /JSONStream@1.3.5: resolution: {integrity: sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==} hasBin: true @@ -2507,6 +2562,11 @@ packages: hasBin: true dev: false + /uuid@9.0.1: + resolution: {integrity: sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==} + hasBin: true + dev: false + /vlq@2.0.4: resolution: {integrity: sha512-aodjPa2wPQFkra1G8CzJBTHXhgk3EVSwxSWXNPr1fgdFLUb8kvLV1iEb6rFgasIsjP82HWI6dsb5Io26DDnasA==} dev: false diff --git a/packages/networks/solana/src/browser/Wallet.ts b/packages/networks/solana/src/browser/Wallet.ts index 9f60a5b..156d929 100644 --- a/packages/networks/solana/src/browser/Wallet.ts +++ b/packages/networks/solana/src/browser/Wallet.ts @@ -12,6 +12,7 @@ import type { WalletAdapterEvents } from '@solana/wallet-adapter-base' import { base58Encode } from '@multiplechain/utils' +import type { TransactionSigner } from '../services/TransactionSigner.ts' const rejectMap = (error: any, reject: (a: any) => any): any => { console.error('MultipleChain Solana Wallet Error:', error) @@ -40,12 +41,14 @@ const rejectMap = (error: any, reject: (a: any) => any): any => { 'WalletConnectionError', 'WalletWindowClosedError', 'WalletAccountError', - 'WalletSendTransactionError' + 'WalletSendTransactionError', + 'WalletSignMessageError' ].includes(String(error.name)) || error.code === 4001 || errorMessage === 'User rejected the request.' || error.name === 'WalletSignTransactionError' || errorMessage.includes('user reject this request') || + errorMessage.includes('Transaction rejected') || errorMessage === 'User canceled request' ) { return reject(new Error(ErrorTypeEnum.WALLET_REQUEST_REJECTED)) @@ -206,18 +209,18 @@ export class Wallet implements WalletInterface { * @param {TransactionSignerInterface} transactionSigner * @returns {Promise} */ - async sendTransaction(transactionSigner: TransactionSignerInterface): Promise { + async sendTransaction(_transactionSigner: TransactionSignerInterface): Promise { + const transactionSigner = _transactionSigner as TransactionSigner return await new Promise((resolve, reject) => { this.currentReject = reject try { void (async () => { - const recentBlockhash = ( - await this.networkProvider.web3.getLatestBlockhash('finalized') - ).blockhash - const tx = await this.walletProvider.signTransaction( - Object.assign(transactionSigner.getRawData(), { recentBlockhash }) + resolve( + await this.walletProvider.sendTransaction( + transactionSigner.getRawData(), + this.networkProvider.web3 + ) ) - resolve(base58Encode(tx.signature as Uint8Array)) })() } catch (error) { rejectMap(error, reject) diff --git a/packages/networks/solana/src/browser/adapters/Solflare.ts b/packages/networks/solana/src/browser/adapters/Solflare.ts new file mode 100644 index 0000000..b04350c --- /dev/null +++ b/packages/networks/solana/src/browser/adapters/Solflare.ts @@ -0,0 +1,48 @@ +import { WalletPlatformEnum } from '@multiplechain/types' +import { SolflareWalletAdapter } from '@solana/wallet-adapter-solflare' +import type { ProviderInterface, WalletAdapterInterface } from '@multiplechain/types' +import { + WalletReadyState, + WalletAdapterNetwork, + type BaseMessageSignerWalletAdapter +} from '@solana/wallet-adapter-base' + +const solflare = new SolflareWalletAdapter() + +declare global { + interface Window { + solflare?: { + isSolflare?: boolean + } + } +} + +const Solflare: WalletAdapterInterface = { + id: 'solflare', + name: solflare.name, + icon: solflare.icon, + platforms: [WalletPlatformEnum.BROWSER, WalletPlatformEnum.MOBILE], + downloadLink: 'https://solflare.com/download#extension', + createDeepLink(url: string, _ops?: object): string { + return `https://solflare.com/ul/v1/browse/${url}?ref=${url}` + }, + isDetected: () => solflare.readyState === WalletReadyState.Installed, + isConnected: async () => { + return true // return true if connected + }, + connect: async ( + _provider?: ProviderInterface, + _ops?: object + ): Promise => { + const solflare = new SolflareWalletAdapter({ + network: + _provider !== undefined && _provider?.isTestnet() + ? WalletAdapterNetwork.Devnet + : WalletAdapterNetwork.Mainnet + }) + await solflare.connect() + return solflare + } +} + +export default Solflare diff --git a/packages/networks/solana/src/browser/adapters/index.ts b/packages/networks/solana/src/browser/adapters/index.ts index 2b7b60e..12e3cf3 100644 --- a/packages/networks/solana/src/browser/adapters/index.ts +++ b/packages/networks/solana/src/browser/adapters/index.ts @@ -1 +1,2 @@ -export { default as Example } from './Phantom.ts' +export { default as Phantom } from './Phantom.ts' +export { default as Solflare } from './Solflare.ts' From 0817efb578b0bf41ba3cc6b81e13bac5706c7dda Mon Sep 17 00:00:00 2001 From: Halil Beycan <50718965+BeycanDeveloper@users.noreply.github.com> Date: Tue, 21 May 2024 17:58:47 +0800 Subject: [PATCH 79/90] slope completed --- packages/networks/solana/package.json | 1 + packages/networks/solana/pnpm-lock.yaml | 15 +++++++++++ .../solana/src/browser/adapters/Phantom.ts | 4 +-- .../solana/src/browser/adapters/Slope.ts | 25 +++++++++++++++++++ .../solana/src/browser/adapters/Solflare.ts | 4 +-- .../solana/src/browser/adapters/index.ts | 1 + 6 files changed, 44 insertions(+), 6 deletions(-) create mode 100644 packages/networks/solana/src/browser/adapters/Slope.ts diff --git a/packages/networks/solana/package.json b/packages/networks/solana/package.json index aebf398..7ccaff1 100644 --- a/packages/networks/solana/package.json +++ b/packages/networks/solana/package.json @@ -69,6 +69,7 @@ "@solana/spl-token-metadata": "^0.1.4", "@solana/wallet-adapter-base": "^0.9.23", "@solana/wallet-adapter-phantom": "^0.9.24", + "@solana/wallet-adapter-slope": "^0.5.21", "@solana/wallet-adapter-solflare": "^0.6.28", "@solana/web3.js": "^1.91.8", "axios": "^1.6.8" diff --git a/packages/networks/solana/pnpm-lock.yaml b/packages/networks/solana/pnpm-lock.yaml index 9aaeca5..786ca4b 100644 --- a/packages/networks/solana/pnpm-lock.yaml +++ b/packages/networks/solana/pnpm-lock.yaml @@ -26,6 +26,9 @@ dependencies: '@solana/wallet-adapter-phantom': specifier: ^0.9.24 version: 0.9.24(@solana/web3.js@1.91.8) + '@solana/wallet-adapter-slope': + specifier: ^0.5.21 + version: 0.5.21(@solana/web3.js@1.91.8) '@solana/wallet-adapter-solflare': specifier: ^0.6.28 version: 0.6.28(@solana/web3.js@1.91.8) @@ -1048,6 +1051,18 @@ packages: '@solana/web3.js': 1.91.8 dev: false + /@solana/wallet-adapter-slope@0.5.21(@solana/web3.js@1.91.8): + resolution: {integrity: sha512-4byuSwqkt8L3w7VzFvVPBN+lNkx7CmEc+FMFZUuo9pBDwwi6sDYZK/+wBBep7L7+xW81XKN9K4MsMOQAD2snSg==} + engines: {node: '>=16'} + deprecated: Package no longer supported. Contact Support at https://www.npmjs.com/support for more info. + peerDependencies: + '@solana/web3.js': ^1.77.3 + dependencies: + '@solana/wallet-adapter-base': 0.9.23(@solana/web3.js@1.91.8) + '@solana/web3.js': 1.91.8 + bs58: 4.0.1 + dev: false + /@solana/wallet-adapter-solflare@0.6.28(@solana/web3.js@1.91.8): resolution: {integrity: sha512-iiUQtuXp8p4OdruDawsm1dRRnzUCcsu+lKo8OezESskHtbmZw2Ifej0P99AbJbBAcBw7q4GPI6987Vh05Si5rw==} engines: {node: '>=16'} diff --git a/packages/networks/solana/src/browser/adapters/Phantom.ts b/packages/networks/solana/src/browser/adapters/Phantom.ts index c7e8a84..be4d3d1 100644 --- a/packages/networks/solana/src/browser/adapters/Phantom.ts +++ b/packages/networks/solana/src/browser/adapters/Phantom.ts @@ -29,9 +29,7 @@ const Phantom: WalletAdapterInterface = { Boolean( window.phantom?.solana?.isPhantom !== undefined && window.phantom?.connect === undefined ), - isConnected: async () => { - return true // return true if connected - }, + isConnected: async () => phantomAdapter.connected, connect: async ( _provider?: ProviderInterface, _ops?: object diff --git a/packages/networks/solana/src/browser/adapters/Slope.ts b/packages/networks/solana/src/browser/adapters/Slope.ts new file mode 100644 index 0000000..afe2a6e --- /dev/null +++ b/packages/networks/solana/src/browser/adapters/Slope.ts @@ -0,0 +1,25 @@ +import { WalletPlatformEnum } from '@multiplechain/types' +import { SlopeWalletAdapter } from '@solana/wallet-adapter-slope' +import type { ProviderInterface, WalletAdapterInterface } from '@multiplechain/types' +import { WalletReadyState, type BaseMessageSignerWalletAdapter } from '@solana/wallet-adapter-base' + +const slope = new SlopeWalletAdapter() + +const Slope: WalletAdapterInterface = { + id: 'slope', + name: slope.name, + icon: slope.icon, + platforms: [WalletPlatformEnum.BROWSER], + downloadLink: 'https://www.slope.finance/', + isDetected: () => slope.readyState === WalletReadyState.Installed, + isConnected: async () => slope.connected, + connect: async ( + _provider?: ProviderInterface, + _ops?: object + ): Promise => { + await slope.connect() + return slope as BaseMessageSignerWalletAdapter + } +} + +export default Slope diff --git a/packages/networks/solana/src/browser/adapters/Solflare.ts b/packages/networks/solana/src/browser/adapters/Solflare.ts index b04350c..d1fb2fa 100644 --- a/packages/networks/solana/src/browser/adapters/Solflare.ts +++ b/packages/networks/solana/src/browser/adapters/Solflare.ts @@ -27,9 +27,7 @@ const Solflare: WalletAdapterInterface = { return `https://solflare.com/ul/v1/browse/${url}?ref=${url}` }, isDetected: () => solflare.readyState === WalletReadyState.Installed, - isConnected: async () => { - return true // return true if connected - }, + isConnected: async () => solflare.connected, connect: async ( _provider?: ProviderInterface, _ops?: object diff --git a/packages/networks/solana/src/browser/adapters/index.ts b/packages/networks/solana/src/browser/adapters/index.ts index 12e3cf3..d32e390 100644 --- a/packages/networks/solana/src/browser/adapters/index.ts +++ b/packages/networks/solana/src/browser/adapters/index.ts @@ -1,2 +1,3 @@ +export { default as Slope } from './Slope.ts' export { default as Phantom } from './Phantom.ts' export { default as Solflare } from './Solflare.ts' From d000ce832577a6c7174490cc3dacc5bc11f452e6 Mon Sep 17 00:00:00 2001 From: Halil Beycan <50718965+BeycanDeveloper@users.noreply.github.com> Date: Tue, 21 May 2024 18:15:09 +0800 Subject: [PATCH 80/90] completed trustwallet --- packages/networks/solana/index.html | 2 +- packages/networks/solana/package.json | 1 + packages/networks/solana/pnpm-lock.yaml | 13 ++++++++ .../solana/src/browser/adapters/Phantom.ts | 3 ++ .../solana/src/browser/adapters/Slope.ts | 3 ++ .../solana/src/browser/adapters/Solflare.ts | 3 ++ .../src/browser/adapters/TrustWallet.ts | 31 +++++++++++++++++++ .../solana/src/browser/adapters/index.ts | 1 + 8 files changed, 56 insertions(+), 1 deletion(-) create mode 100644 packages/networks/solana/src/browser/adapters/TrustWallet.ts diff --git a/packages/networks/solana/index.html b/packages/networks/solana/index.html index 3727ef9..41bee00 100644 --- a/packages/networks/solana/index.html +++ b/packages/networks/solana/index.html @@ -216,7 +216,7 @@ window.Solana = Solana const provider = new Solana.Provider({ - testnet: true, + testnet: true }); window.adapters = {} diff --git a/packages/networks/solana/package.json b/packages/networks/solana/package.json index 7ccaff1..373457c 100644 --- a/packages/networks/solana/package.json +++ b/packages/networks/solana/package.json @@ -71,6 +71,7 @@ "@solana/wallet-adapter-phantom": "^0.9.24", "@solana/wallet-adapter-slope": "^0.5.21", "@solana/wallet-adapter-solflare": "^0.6.28", + "@solana/wallet-adapter-trust": "^0.1.13", "@solana/web3.js": "^1.91.8", "axios": "^1.6.8" } diff --git a/packages/networks/solana/pnpm-lock.yaml b/packages/networks/solana/pnpm-lock.yaml index 786ca4b..35ea536 100644 --- a/packages/networks/solana/pnpm-lock.yaml +++ b/packages/networks/solana/pnpm-lock.yaml @@ -32,6 +32,9 @@ dependencies: '@solana/wallet-adapter-solflare': specifier: ^0.6.28 version: 0.6.28(@solana/web3.js@1.91.8) + '@solana/wallet-adapter-trust': + specifier: ^0.1.13 + version: 0.1.13(@solana/web3.js@1.91.8) '@solana/web3.js': specifier: ^1.91.8 version: 1.91.8 @@ -1077,6 +1080,16 @@ packages: '@wallet-standard/wallet': 1.0.1 dev: false + /@solana/wallet-adapter-trust@0.1.13(@solana/web3.js@1.91.8): + resolution: {integrity: sha512-lkmPfNdyRgx+z0K7i2cDa3a6SOKXpi3FiaYSo8Zozoxkp+Ga/NXVWxlXtMca4GAc/MnJMVp7yF/31kyFIee+3A==} + engines: {node: '>=16'} + peerDependencies: + '@solana/web3.js': ^1.77.3 + dependencies: + '@solana/wallet-adapter-base': 0.9.23(@solana/web3.js@1.91.8) + '@solana/web3.js': 1.91.8 + dev: false + /@solana/wallet-standard-chains@1.1.0: resolution: {integrity: sha512-IRJHf94UZM8AaRRmY18d34xCJiVPJej1XVwXiTjihHnmwD0cxdQbc/CKjrawyqFyQAKJx7raE5g9mnJsAdspTg==} engines: {node: '>=16'} diff --git a/packages/networks/solana/src/browser/adapters/Phantom.ts b/packages/networks/solana/src/browser/adapters/Phantom.ts index be4d3d1..51a77ad 100644 --- a/packages/networks/solana/src/browser/adapters/Phantom.ts +++ b/packages/networks/solana/src/browser/adapters/Phantom.ts @@ -30,6 +30,9 @@ const Phantom: WalletAdapterInterface = { window.phantom?.solana?.isPhantom !== undefined && window.phantom?.connect === undefined ), isConnected: async () => phantomAdapter.connected, + disconnect: async () => { + await phantomAdapter.disconnect() + }, connect: async ( _provider?: ProviderInterface, _ops?: object diff --git a/packages/networks/solana/src/browser/adapters/Slope.ts b/packages/networks/solana/src/browser/adapters/Slope.ts index afe2a6e..1d7fbe6 100644 --- a/packages/networks/solana/src/browser/adapters/Slope.ts +++ b/packages/networks/solana/src/browser/adapters/Slope.ts @@ -13,6 +13,9 @@ const Slope: WalletAdapterInterface = { downloadLink: 'https://www.slope.finance/', isDetected: () => slope.readyState === WalletReadyState.Installed, isConnected: async () => slope.connected, + disconnect: async () => { + await slope.disconnect() + }, connect: async ( _provider?: ProviderInterface, _ops?: object diff --git a/packages/networks/solana/src/browser/adapters/Solflare.ts b/packages/networks/solana/src/browser/adapters/Solflare.ts index d1fb2fa..69b453a 100644 --- a/packages/networks/solana/src/browser/adapters/Solflare.ts +++ b/packages/networks/solana/src/browser/adapters/Solflare.ts @@ -28,6 +28,9 @@ const Solflare: WalletAdapterInterface = { }, isDetected: () => solflare.readyState === WalletReadyState.Installed, isConnected: async () => solflare.connected, + disconnect: async () => { + await solflare.disconnect() + }, connect: async ( _provider?: ProviderInterface, _ops?: object diff --git a/packages/networks/solana/src/browser/adapters/TrustWallet.ts b/packages/networks/solana/src/browser/adapters/TrustWallet.ts new file mode 100644 index 0000000..3ed7a93 --- /dev/null +++ b/packages/networks/solana/src/browser/adapters/TrustWallet.ts @@ -0,0 +1,31 @@ +import { WalletPlatformEnum } from '@multiplechain/types' +import { TrustWalletAdapter } from '@solana/wallet-adapter-trust' +import type { ProviderInterface, WalletAdapterInterface } from '@multiplechain/types' +import { WalletReadyState, type BaseMessageSignerWalletAdapter } from '@solana/wallet-adapter-base' + +const trustIcon = + 'data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNTgiIGhlaWdodD0iNjUiIHZpZXdCb3g9IjAgMCA1OCA2NSIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZD0iTTAgOS4zODk0OUwyOC44OTA3IDBWNjUuMDA0MkM4LjI1NDUgNTYuMzM2OSAwIDM5LjcyNDggMCAzMC4zMzUzVjkuMzg5NDlaIiBmaWxsPSIjMDUwMEZGIi8+CjxwYXRoIGQ9Ik01Ny43ODIyIDkuMzg5NDlMMjguODkxNSAwVjY1LjAwNDJDNDkuNTI3NyA1Ni4zMzY5IDU3Ljc4MjIgMzkuNzI0OCA1Ny43ODIyIDMwLjMzNTNWOS4zODk0OVoiIGZpbGw9InVybCgjcGFpbnQwX2xpbmVhcl8yMjAxXzY5NDIpIi8+CjxkZWZzPgo8bGluZWFyR3JhZGllbnQgaWQ9InBhaW50MF9saW5lYXJfMjIwMV82OTQyIiB4MT0iNTEuMzYxNSIgeTE9Ii00LjE1MjkzIiB4Mj0iMjkuNTM4NCIgeTI9IjY0LjUxNDciIGdyYWRpZW50VW5pdHM9InVzZXJTcGFjZU9uVXNlIj4KPHN0b3Agb2Zmc2V0PSIwLjAyMTEyIiBzdG9wLWNvbG9yPSIjMDAwMEZGIi8+CjxzdG9wIG9mZnNldD0iMC4wNzYyNDIzIiBzdG9wLWNvbG9yPSIjMDA5NEZGIi8+CjxzdG9wIG9mZnNldD0iMC4xNjMwODkiIHN0b3AtY29sb3I9IiM0OEZGOTEiLz4KPHN0b3Agb2Zmc2V0PSIwLjQyMDA0OSIgc3RvcC1jb2xvcj0iIzAwOTRGRiIvPgo8c3RvcCBvZmZzZXQ9IjAuNjgyODg2IiBzdG9wLWNvbG9yPSIjMDAzOEZGIi8+CjxzdG9wIG9mZnNldD0iMC45MDI0NjUiIHN0b3AtY29sb3I9IiMwNTAwRkYiLz4KPC9saW5lYXJHcmFkaWVudD4KPC9kZWZzPgo8L3N2Zz4K' + +const trust = new TrustWalletAdapter() + +const TrustWallet: WalletAdapterInterface = { + id: 'trustwallet', + name: 'TrustWallet', + icon: trustIcon, + platforms: [WalletPlatformEnum.BROWSER, WalletPlatformEnum.MOBILE], + downloadLink: 'https://trustwallet.com/download', + isDetected: () => trust.readyState === WalletReadyState.Installed, + isConnected: async () => trust.connected, + disconnect: async () => { + await trust.disconnect() + }, + connect: async ( + _provider?: ProviderInterface, + _ops?: object + ): Promise => { + await trust.connect() + return trust as BaseMessageSignerWalletAdapter + } +} + +export default TrustWallet diff --git a/packages/networks/solana/src/browser/adapters/index.ts b/packages/networks/solana/src/browser/adapters/index.ts index d32e390..8e00100 100644 --- a/packages/networks/solana/src/browser/adapters/index.ts +++ b/packages/networks/solana/src/browser/adapters/index.ts @@ -1,3 +1,4 @@ export { default as Slope } from './Slope.ts' export { default as Phantom } from './Phantom.ts' export { default as Solflare } from './Solflare.ts' +export { default as TrustWallet } from './TrustWallet.ts' From 5d29d3a23bef918bde99a718c3159e8e3b459bc2 Mon Sep 17 00:00:00 2001 From: Halil Beycan <50718965+BeycanDeveloper@users.noreply.github.com> Date: Tue, 21 May 2024 18:28:14 +0800 Subject: [PATCH 81/90] bitget completed --- packages/networks/solana/package.json | 1 + packages/networks/solana/pnpm-lock.yaml | 13 ++++++++ .../src/browser/adapters/BitgetWallet.ts | 31 +++++++++++++++++++ .../solana/src/browser/adapters/index.ts | 1 + 4 files changed, 46 insertions(+) create mode 100644 packages/networks/solana/src/browser/adapters/BitgetWallet.ts diff --git a/packages/networks/solana/package.json b/packages/networks/solana/package.json index 373457c..ff15658 100644 --- a/packages/networks/solana/package.json +++ b/packages/networks/solana/package.json @@ -68,6 +68,7 @@ "@solana/spl-token": "^0.4.6", "@solana/spl-token-metadata": "^0.1.4", "@solana/wallet-adapter-base": "^0.9.23", + "@solana/wallet-adapter-bitkeep": "^0.3.20", "@solana/wallet-adapter-phantom": "^0.9.24", "@solana/wallet-adapter-slope": "^0.5.21", "@solana/wallet-adapter-solflare": "^0.6.28", diff --git a/packages/networks/solana/pnpm-lock.yaml b/packages/networks/solana/pnpm-lock.yaml index 35ea536..9604ec1 100644 --- a/packages/networks/solana/pnpm-lock.yaml +++ b/packages/networks/solana/pnpm-lock.yaml @@ -23,6 +23,9 @@ dependencies: '@solana/wallet-adapter-base': specifier: ^0.9.23 version: 0.9.23(@solana/web3.js@1.91.8) + '@solana/wallet-adapter-bitkeep': + specifier: ^0.3.20 + version: 0.3.20(@solana/web3.js@1.91.8) '@solana/wallet-adapter-phantom': specifier: ^0.9.24 version: 0.9.24(@solana/web3.js@1.91.8) @@ -1044,6 +1047,16 @@ packages: eventemitter3: 4.0.7 dev: false + /@solana/wallet-adapter-bitkeep@0.3.20(@solana/web3.js@1.91.8): + resolution: {integrity: sha512-v6Jd13CZOPNIAX0nFlopAJ3HDvC+MhiB4sde3C8sSnNbjVi9h1WLHBmaUfgqU6mAyhDjWUZjKt4zYlMhLdp/bg==} + engines: {node: '>=16'} + peerDependencies: + '@solana/web3.js': ^1.77.3 + dependencies: + '@solana/wallet-adapter-base': 0.9.23(@solana/web3.js@1.91.8) + '@solana/web3.js': 1.91.8 + dev: false + /@solana/wallet-adapter-phantom@0.9.24(@solana/web3.js@1.91.8): resolution: {integrity: sha512-D24AxRHmRJ4AYoRvijbiuUb9LmC4xLGKLMSJS2ly+zGxVmaPASPM/ThaY/DlYTDL31QvkYtl8RzSR4yIU1gpLg==} engines: {node: '>=16'} diff --git a/packages/networks/solana/src/browser/adapters/BitgetWallet.ts b/packages/networks/solana/src/browser/adapters/BitgetWallet.ts new file mode 100644 index 0000000..be1dead --- /dev/null +++ b/packages/networks/solana/src/browser/adapters/BitgetWallet.ts @@ -0,0 +1,31 @@ +import { WalletPlatformEnum } from '@multiplechain/types' +import { BitgetWalletAdapter } from '@solana/wallet-adapter-bitkeep' +import type { ProviderInterface, WalletAdapterInterface } from '@multiplechain/types' +import { WalletReadyState, type BaseMessageSignerWalletAdapter } from '@solana/wallet-adapter-base' + +const bitget = new BitgetWalletAdapter() + +const BitgetWallet: WalletAdapterInterface = { + id: 'bitgetwallet', + name: bitget.name, + icon: bitget.icon, + platforms: [WalletPlatformEnum.BROWSER, WalletPlatformEnum.MOBILE], + downloadLink: 'https://web3.bitget.com/en/wallet-download?type=3', + createDeepLink(url: string, _ops?: object): string { + return `https://bkcode.vip?action=dapp&url=${url}` + }, + isDetected: () => bitget.readyState === WalletReadyState.Installed, + isConnected: async () => bitget.connected, + disconnect: async () => { + await bitget.disconnect() + }, + connect: async ( + _provider?: ProviderInterface, + _ops?: object + ): Promise => { + await bitget.connect() + return bitget as BaseMessageSignerWalletAdapter + } +} + +export default BitgetWallet diff --git a/packages/networks/solana/src/browser/adapters/index.ts b/packages/networks/solana/src/browser/adapters/index.ts index 8e00100..ccf36eb 100644 --- a/packages/networks/solana/src/browser/adapters/index.ts +++ b/packages/networks/solana/src/browser/adapters/index.ts @@ -2,3 +2,4 @@ export { default as Slope } from './Slope.ts' export { default as Phantom } from './Phantom.ts' export { default as Solflare } from './Solflare.ts' export { default as TrustWallet } from './TrustWallet.ts' +export { default as BitgetWallet } from './BitgetWallet.ts' From 640209e69f89dfb26b94d26858d62231801f32d4 Mon Sep 17 00:00:00 2001 From: Halil Beycan <50718965+BeycanDeveloper@users.noreply.github.com> Date: Tue, 21 May 2024 18:31:06 +0800 Subject: [PATCH 82/90] coinbase completed --- packages/networks/solana/package.json | 1 + packages/networks/solana/pnpm-lock.yaml | 13 ++++++++ .../src/browser/adapters/CoinbaseWallet.ts | 31 +++++++++++++++++++ .../solana/src/browser/adapters/index.ts | 1 + 4 files changed, 46 insertions(+) create mode 100644 packages/networks/solana/src/browser/adapters/CoinbaseWallet.ts diff --git a/packages/networks/solana/package.json b/packages/networks/solana/package.json index ff15658..7ec3cc2 100644 --- a/packages/networks/solana/package.json +++ b/packages/networks/solana/package.json @@ -69,6 +69,7 @@ "@solana/spl-token-metadata": "^0.1.4", "@solana/wallet-adapter-base": "^0.9.23", "@solana/wallet-adapter-bitkeep": "^0.3.20", + "@solana/wallet-adapter-coinbase": "^0.1.19", "@solana/wallet-adapter-phantom": "^0.9.24", "@solana/wallet-adapter-slope": "^0.5.21", "@solana/wallet-adapter-solflare": "^0.6.28", diff --git a/packages/networks/solana/pnpm-lock.yaml b/packages/networks/solana/pnpm-lock.yaml index 9604ec1..b47b349 100644 --- a/packages/networks/solana/pnpm-lock.yaml +++ b/packages/networks/solana/pnpm-lock.yaml @@ -26,6 +26,9 @@ dependencies: '@solana/wallet-adapter-bitkeep': specifier: ^0.3.20 version: 0.3.20(@solana/web3.js@1.91.8) + '@solana/wallet-adapter-coinbase': + specifier: ^0.1.19 + version: 0.1.19(@solana/web3.js@1.91.8) '@solana/wallet-adapter-phantom': specifier: ^0.9.24 version: 0.9.24(@solana/web3.js@1.91.8) @@ -1057,6 +1060,16 @@ packages: '@solana/web3.js': 1.91.8 dev: false + /@solana/wallet-adapter-coinbase@0.1.19(@solana/web3.js@1.91.8): + resolution: {integrity: sha512-hcf9ieAbQxD2g8/5glXVAt67w+3iixpjMMZC7lT7Wa8SJZsq6lmISC9AtZctDEQcWSVV0IkedZp3bg6bp22kng==} + engines: {node: '>=16'} + peerDependencies: + '@solana/web3.js': ^1.77.3 + dependencies: + '@solana/wallet-adapter-base': 0.9.23(@solana/web3.js@1.91.8) + '@solana/web3.js': 1.91.8 + dev: false + /@solana/wallet-adapter-phantom@0.9.24(@solana/web3.js@1.91.8): resolution: {integrity: sha512-D24AxRHmRJ4AYoRvijbiuUb9LmC4xLGKLMSJS2ly+zGxVmaPASPM/ThaY/DlYTDL31QvkYtl8RzSR4yIU1gpLg==} engines: {node: '>=16'} diff --git a/packages/networks/solana/src/browser/adapters/CoinbaseWallet.ts b/packages/networks/solana/src/browser/adapters/CoinbaseWallet.ts new file mode 100644 index 0000000..a5205ac --- /dev/null +++ b/packages/networks/solana/src/browser/adapters/CoinbaseWallet.ts @@ -0,0 +1,31 @@ +import { WalletPlatformEnum } from '@multiplechain/types' +import { CoinbaseWalletAdapter } from '@solana/wallet-adapter-coinbase' +import type { ProviderInterface, WalletAdapterInterface } from '@multiplechain/types' +import { WalletReadyState, type BaseMessageSignerWalletAdapter } from '@solana/wallet-adapter-base' + +const coinbase = new CoinbaseWalletAdapter() + +const CoinbaseWallet: WalletAdapterInterface = { + id: 'coinbasewallet', + name: coinbase.name, + icon: coinbase.icon, + platforms: [WalletPlatformEnum.BROWSER, WalletPlatformEnum.MOBILE], + downloadLink: 'https://www.coinbase.com/wallet/downloads', + createDeepLink(url: string, _ops?: object): string { + return `https://go.cb-w.com/dapp?cb_url=${url}` + }, + isDetected: () => coinbase.readyState === WalletReadyState.Installed, + isConnected: async () => coinbase.connected, + disconnect: async () => { + await coinbase.disconnect() + }, + connect: async ( + _provider?: ProviderInterface, + _ops?: object + ): Promise => { + await coinbase.connect() + return coinbase + } +} + +export default CoinbaseWallet diff --git a/packages/networks/solana/src/browser/adapters/index.ts b/packages/networks/solana/src/browser/adapters/index.ts index ccf36eb..621d45f 100644 --- a/packages/networks/solana/src/browser/adapters/index.ts +++ b/packages/networks/solana/src/browser/adapters/index.ts @@ -3,3 +3,4 @@ export { default as Phantom } from './Phantom.ts' export { default as Solflare } from './Solflare.ts' export { default as TrustWallet } from './TrustWallet.ts' export { default as BitgetWallet } from './BitgetWallet.ts' +export { default as CoinbaseWallet } from './CoinbaseWallet.ts' From bfdccfe16ebe4a2eca5bbdde24bc6eeb1b0e2a53 Mon Sep 17 00:00:00 2001 From: Halil Beycan <50718965+BeycanDeveloper@users.noreply.github.com> Date: Tue, 21 May 2024 18:42:18 +0800 Subject: [PATCH 83/90] added tokenpocket --- packages/networks/solana/package.json | 1 + packages/networks/solana/pnpm-lock.yaml | 13 +++++++ .../src/browser/adapters/TokenPocket.ts | 38 +++++++++++++++++++ .../solana/src/browser/adapters/index.ts | 1 + 4 files changed, 53 insertions(+) create mode 100644 packages/networks/solana/src/browser/adapters/TokenPocket.ts diff --git a/packages/networks/solana/package.json b/packages/networks/solana/package.json index 7ec3cc2..779f606 100644 --- a/packages/networks/solana/package.json +++ b/packages/networks/solana/package.json @@ -73,6 +73,7 @@ "@solana/wallet-adapter-phantom": "^0.9.24", "@solana/wallet-adapter-slope": "^0.5.21", "@solana/wallet-adapter-solflare": "^0.6.28", + "@solana/wallet-adapter-tokenpocket": "^0.4.19", "@solana/wallet-adapter-trust": "^0.1.13", "@solana/web3.js": "^1.91.8", "axios": "^1.6.8" diff --git a/packages/networks/solana/pnpm-lock.yaml b/packages/networks/solana/pnpm-lock.yaml index b47b349..7d22b74 100644 --- a/packages/networks/solana/pnpm-lock.yaml +++ b/packages/networks/solana/pnpm-lock.yaml @@ -38,6 +38,9 @@ dependencies: '@solana/wallet-adapter-solflare': specifier: ^0.6.28 version: 0.6.28(@solana/web3.js@1.91.8) + '@solana/wallet-adapter-tokenpocket': + specifier: ^0.4.19 + version: 0.4.19(@solana/web3.js@1.91.8) '@solana/wallet-adapter-trust': specifier: ^0.1.13 version: 0.1.13(@solana/web3.js@1.91.8) @@ -1106,6 +1109,16 @@ packages: '@wallet-standard/wallet': 1.0.1 dev: false + /@solana/wallet-adapter-tokenpocket@0.4.19(@solana/web3.js@1.91.8): + resolution: {integrity: sha512-zKXTN+tuKIr/stSxUeG9XPBks9iqeliBWS9JF8eq+8u/Qb/bIDbNSQmd8Z5u1x2lf0puiStc9/iUu/+MLaOSVg==} + engines: {node: '>=16'} + peerDependencies: + '@solana/web3.js': ^1.77.3 + dependencies: + '@solana/wallet-adapter-base': 0.9.23(@solana/web3.js@1.91.8) + '@solana/web3.js': 1.91.8 + dev: false + /@solana/wallet-adapter-trust@0.1.13(@solana/web3.js@1.91.8): resolution: {integrity: sha512-lkmPfNdyRgx+z0K7i2cDa3a6SOKXpi3FiaYSo8Zozoxkp+Ga/NXVWxlXtMca4GAc/MnJMVp7yF/31kyFIee+3A==} engines: {node: '>=16'} diff --git a/packages/networks/solana/src/browser/adapters/TokenPocket.ts b/packages/networks/solana/src/browser/adapters/TokenPocket.ts new file mode 100644 index 0000000..12725d6 --- /dev/null +++ b/packages/networks/solana/src/browser/adapters/TokenPocket.ts @@ -0,0 +1,38 @@ +import { WalletPlatformEnum } from '@multiplechain/types' +import { TokenPocketWalletAdapter } from '@solana/wallet-adapter-tokenpocket' +import type { ProviderInterface, WalletAdapterInterface } from '@multiplechain/types' +import { WalletReadyState, type BaseMessageSignerWalletAdapter } from '@solana/wallet-adapter-base' + +const tokenPocket = new TokenPocketWalletAdapter() + +const TokenPocket: WalletAdapterInterface = { + id: 'tokenpocket', + name: tokenPocket.name, + icon: tokenPocket.icon, + platforms: [WalletPlatformEnum.MOBILE], + downloadLink: 'https://www.tokenpocket.pro/en/download/app', + createDeepLink(url: string, _ops?: object): string { + return ( + 'tpdapp://open?params=' + + JSON.stringify({ + url, + chain: 'Solana', + source: url + }) + ) + }, + isDetected: () => tokenPocket.readyState === WalletReadyState.Installed, + isConnected: async () => tokenPocket.connected, + disconnect: async () => { + await tokenPocket.disconnect() + }, + connect: async ( + _provider?: ProviderInterface, + _ops?: object + ): Promise => { + await tokenPocket.connect() + return tokenPocket as BaseMessageSignerWalletAdapter + } +} + +export default TokenPocket diff --git a/packages/networks/solana/src/browser/adapters/index.ts b/packages/networks/solana/src/browser/adapters/index.ts index 621d45f..cb0c6fd 100644 --- a/packages/networks/solana/src/browser/adapters/index.ts +++ b/packages/networks/solana/src/browser/adapters/index.ts @@ -2,5 +2,6 @@ export { default as Slope } from './Slope.ts' export { default as Phantom } from './Phantom.ts' export { default as Solflare } from './Solflare.ts' export { default as TrustWallet } from './TrustWallet.ts' +export { default as TokenPocket } from './TokenPocket.ts' export { default as BitgetWallet } from './BitgetWallet.ts' export { default as CoinbaseWallet } from './CoinbaseWallet.ts' From aefb0ed3e72691bbd13f5bde3573d02cd7c62a0b Mon Sep 17 00:00:00 2001 From: Halil Beycan <50718965+BeycanDeveloper@users.noreply.github.com> Date: Tue, 21 May 2024 18:55:31 +0800 Subject: [PATCH 84/90] removed wrong properties --- .../tron/src/browser/adapters/WalletConnect.ts | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/packages/networks/tron/src/browser/adapters/WalletConnect.ts b/packages/networks/tron/src/browser/adapters/WalletConnect.ts index 5f95416..13466e9 100644 --- a/packages/networks/tron/src/browser/adapters/WalletConnect.ts +++ b/packages/networks/tron/src/browser/adapters/WalletConnect.ts @@ -17,18 +17,6 @@ const WalletConnect: WalletAdapterInterface = { id: 'walletconnect', name: 'WalletConnect', platforms: [WalletPlatformEnum.UNIVERSAL], - downloadLink: 'https://www.tronlink.org/dlDetails/', - createDeepLink(url: string): string { - return ( - 'tronlinkoutside://pull.activity?param=' + - JSON.stringify({ - url, - action: 'open', - protocol: 'tronlink', - version: '1.0' - }) - ) - }, isDetected: () => true, isConnected: () => isConnected, disconnect: async () => { From 01499060bb0a4a99d918e622ad56e3885112281c Mon Sep 17 00:00:00 2001 From: Halil Beycan <50718965+BeycanDeveloper@users.noreply.github.com> Date: Tue, 21 May 2024 18:58:19 +0800 Subject: [PATCH 85/90] added connected option --- packages/networks/tron/src/browser/adapters/WalletConnect.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/networks/tron/src/browser/adapters/WalletConnect.ts b/packages/networks/tron/src/browser/adapters/WalletConnect.ts index 13466e9..61807a7 100644 --- a/packages/networks/tron/src/browser/adapters/WalletConnect.ts +++ b/packages/networks/tron/src/browser/adapters/WalletConnect.ts @@ -68,6 +68,7 @@ const WalletConnect: WalletAdapterInterface = { walletProvider .connect() .then(async () => { + isConnected = true resolve(walletProvider as CustomAdapter) }) .catch((error) => { From 857ff17c57b9bb4c7493a042a3303dda777c7265 Mon Sep 17 00:00:00 2001 From: Halil Beycan <50718965+BeycanDeveloper@users.noreply.github.com> Date: Tue, 21 May 2024 19:16:07 +0800 Subject: [PATCH 86/90] updated --- packages/networks/tron/src/browser/adapters/WalletConnect.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/networks/tron/src/browser/adapters/WalletConnect.ts b/packages/networks/tron/src/browser/adapters/WalletConnect.ts index 61807a7..dc32273 100644 --- a/packages/networks/tron/src/browser/adapters/WalletConnect.ts +++ b/packages/networks/tron/src/browser/adapters/WalletConnect.ts @@ -28,7 +28,7 @@ const WalletConnect: WalletAdapterInterface = { }) localStorage.removeItem('walletconnect') localStorage.removeItem('WALLETCONNECT_DEEPLINK_CHOICE') - document.cookie = 'wl-connected' + '=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;' + indexedDB.deleteDatabase('WALLET_CONNECT_V2_INDEXED_DB') }, connect: async ( provider?: ProviderInterface, From c117f81019daedc715a0595ca51af598fd6734f1 Mon Sep 17 00:00:00 2001 From: Halil Beycan <50718965+BeycanDeveloper@users.noreply.github.com> Date: Tue, 21 May 2024 19:16:28 +0800 Subject: [PATCH 87/90] added WalletConnect --- packages/networks/solana/package.json | 1 + packages/networks/solana/pnpm-lock.yaml | 2544 ++++++++++++++++- .../src/browser/adapters/WalletConnect.ts | 79 + .../solana/src/browser/adapters/index.ts | 1 + 4 files changed, 2608 insertions(+), 17 deletions(-) create mode 100644 packages/networks/solana/src/browser/adapters/WalletConnect.ts diff --git a/packages/networks/solana/package.json b/packages/networks/solana/package.json index 779f606..049bcce 100644 --- a/packages/networks/solana/package.json +++ b/packages/networks/solana/package.json @@ -63,6 +63,7 @@ }, "dependencies": { "@metaplex-foundation/js": "^0.20.1", + "@multiplechain/solana-walletconnect": "^0.1.1", "@multiplechain/types": "^0.1.56", "@multiplechain/utils": "^0.1.20", "@solana/spl-token": "^0.4.6", diff --git a/packages/networks/solana/pnpm-lock.yaml b/packages/networks/solana/pnpm-lock.yaml index 7d22b74..f964a4d 100644 --- a/packages/networks/solana/pnpm-lock.yaml +++ b/packages/networks/solana/pnpm-lock.yaml @@ -8,6 +8,9 @@ dependencies: '@metaplex-foundation/js': specifier: ^0.20.1 version: 0.20.1(arweave@1.15.1)(fastestsmallesttextencoderdecoder@1.0.22) + '@multiplechain/solana-walletconnect': + specifier: ^0.1.1 + version: 0.1.1(@solana/web3.js@1.91.8)(vite@5.2.11) '@multiplechain/types': specifier: ^0.1.56 version: 0.1.56 @@ -60,6 +63,213 @@ packages: regenerator-runtime: 0.14.1 dev: false + /@esbuild/aix-ppc64@0.20.2: + resolution: {integrity: sha512-D+EBOJHXdNZcLJRBkhENNG8Wji2kgc9AZ9KiPr1JuZjsNtyHzrsfLRrY0tk2H2aoFu6RANO1y1iPPUCDYWkb5g==} + engines: {node: '>=12'} + cpu: [ppc64] + os: [aix] + requiresBuild: true + dev: false + optional: true + + /@esbuild/android-arm64@0.20.2: + resolution: {integrity: sha512-mRzjLacRtl/tWU0SvD8lUEwb61yP9cqQo6noDZP/O8VkwafSYwZ4yWy24kan8jE/IMERpYncRt2dw438LP3Xmg==} + engines: {node: '>=12'} + cpu: [arm64] + os: [android] + requiresBuild: true + dev: false + optional: true + + /@esbuild/android-arm@0.20.2: + resolution: {integrity: sha512-t98Ra6pw2VaDhqNWO2Oph2LXbz/EJcnLmKLGBJwEwXX/JAN83Fym1rU8l0JUWK6HkIbWONCSSatf4sf2NBRx/w==} + engines: {node: '>=12'} + cpu: [arm] + os: [android] + requiresBuild: true + dev: false + optional: true + + /@esbuild/android-x64@0.20.2: + resolution: {integrity: sha512-btzExgV+/lMGDDa194CcUQm53ncxzeBrWJcncOBxuC6ndBkKxnHdFJn86mCIgTELsooUmwUm9FkhSp5HYu00Rg==} + engines: {node: '>=12'} + cpu: [x64] + os: [android] + requiresBuild: true + dev: false + optional: true + + /@esbuild/darwin-arm64@0.20.2: + resolution: {integrity: sha512-4J6IRT+10J3aJH3l1yzEg9y3wkTDgDk7TSDFX+wKFiWjqWp/iCfLIYzGyasx9l0SAFPT1HwSCR+0w/h1ES/MjA==} + engines: {node: '>=12'} + cpu: [arm64] + os: [darwin] + requiresBuild: true + dev: false + optional: true + + /@esbuild/darwin-x64@0.20.2: + resolution: {integrity: sha512-tBcXp9KNphnNH0dfhv8KYkZhjc+H3XBkF5DKtswJblV7KlT9EI2+jeA8DgBjp908WEuYll6pF+UStUCfEpdysA==} + engines: {node: '>=12'} + cpu: [x64] + os: [darwin] + requiresBuild: true + dev: false + optional: true + + /@esbuild/freebsd-arm64@0.20.2: + resolution: {integrity: sha512-d3qI41G4SuLiCGCFGUrKsSeTXyWG6yem1KcGZVS+3FYlYhtNoNgYrWcvkOoaqMhwXSMrZRl69ArHsGJ9mYdbbw==} + engines: {node: '>=12'} + cpu: [arm64] + os: [freebsd] + requiresBuild: true + dev: false + optional: true + + /@esbuild/freebsd-x64@0.20.2: + resolution: {integrity: sha512-d+DipyvHRuqEeM5zDivKV1KuXn9WeRX6vqSqIDgwIfPQtwMP4jaDsQsDncjTDDsExT4lR/91OLjRo8bmC1e+Cw==} + engines: {node: '>=12'} + cpu: [x64] + os: [freebsd] + requiresBuild: true + dev: false + optional: true + + /@esbuild/linux-arm64@0.20.2: + resolution: {integrity: sha512-9pb6rBjGvTFNira2FLIWqDk/uaf42sSyLE8j1rnUpuzsODBq7FvpwHYZxQ/It/8b+QOS1RYfqgGFNLRI+qlq2A==} + engines: {node: '>=12'} + cpu: [arm64] + os: [linux] + requiresBuild: true + dev: false + optional: true + + /@esbuild/linux-arm@0.20.2: + resolution: {integrity: sha512-VhLPeR8HTMPccbuWWcEUD1Az68TqaTYyj6nfE4QByZIQEQVWBB8vup8PpR7y1QHL3CpcF6xd5WVBU/+SBEvGTg==} + engines: {node: '>=12'} + cpu: [arm] + os: [linux] + requiresBuild: true + dev: false + optional: true + + /@esbuild/linux-ia32@0.20.2: + resolution: {integrity: sha512-o10utieEkNPFDZFQm9CoP7Tvb33UutoJqg3qKf1PWVeeJhJw0Q347PxMvBgVVFgouYLGIhFYG0UGdBumROyiig==} + engines: {node: '>=12'} + cpu: [ia32] + os: [linux] + requiresBuild: true + dev: false + optional: true + + /@esbuild/linux-loong64@0.20.2: + resolution: {integrity: sha512-PR7sp6R/UC4CFVomVINKJ80pMFlfDfMQMYynX7t1tNTeivQ6XdX5r2XovMmha/VjR1YN/HgHWsVcTRIMkymrgQ==} + engines: {node: '>=12'} + cpu: [loong64] + os: [linux] + requiresBuild: true + dev: false + optional: true + + /@esbuild/linux-mips64el@0.20.2: + resolution: {integrity: sha512-4BlTqeutE/KnOiTG5Y6Sb/Hw6hsBOZapOVF6njAESHInhlQAghVVZL1ZpIctBOoTFbQyGW+LsVYZ8lSSB3wkjA==} + engines: {node: '>=12'} + cpu: [mips64el] + os: [linux] + requiresBuild: true + dev: false + optional: true + + /@esbuild/linux-ppc64@0.20.2: + resolution: {integrity: sha512-rD3KsaDprDcfajSKdn25ooz5J5/fWBylaaXkuotBDGnMnDP1Uv5DLAN/45qfnf3JDYyJv/ytGHQaziHUdyzaAg==} + engines: {node: '>=12'} + cpu: [ppc64] + os: [linux] + requiresBuild: true + dev: false + optional: true + + /@esbuild/linux-riscv64@0.20.2: + resolution: {integrity: sha512-snwmBKacKmwTMmhLlz/3aH1Q9T8v45bKYGE3j26TsaOVtjIag4wLfWSiZykXzXuE1kbCE+zJRmwp+ZbIHinnVg==} + engines: {node: '>=12'} + cpu: [riscv64] + os: [linux] + requiresBuild: true + dev: false + optional: true + + /@esbuild/linux-s390x@0.20.2: + resolution: {integrity: sha512-wcWISOobRWNm3cezm5HOZcYz1sKoHLd8VL1dl309DiixxVFoFe/o8HnwuIwn6sXre88Nwj+VwZUvJf4AFxkyrQ==} + engines: {node: '>=12'} + cpu: [s390x] + os: [linux] + requiresBuild: true + dev: false + optional: true + + /@esbuild/linux-x64@0.20.2: + resolution: {integrity: sha512-1MdwI6OOTsfQfek8sLwgyjOXAu+wKhLEoaOLTjbijk6E2WONYpH9ZU2mNtR+lZ2B4uwr+usqGuVfFT9tMtGvGw==} + engines: {node: '>=12'} + cpu: [x64] + os: [linux] + requiresBuild: true + dev: false + optional: true + + /@esbuild/netbsd-x64@0.20.2: + resolution: {integrity: sha512-K8/DhBxcVQkzYc43yJXDSyjlFeHQJBiowJ0uVL6Tor3jGQfSGHNNJcWxNbOI8v5k82prYqzPuwkzHt3J1T1iZQ==} + engines: {node: '>=12'} + cpu: [x64] + os: [netbsd] + requiresBuild: true + dev: false + optional: true + + /@esbuild/openbsd-x64@0.20.2: + resolution: {integrity: sha512-eMpKlV0SThJmmJgiVyN9jTPJ2VBPquf6Kt/nAoo6DgHAoN57K15ZghiHaMvqjCye/uU4X5u3YSMgVBI1h3vKrQ==} + engines: {node: '>=12'} + cpu: [x64] + os: [openbsd] + requiresBuild: true + dev: false + optional: true + + /@esbuild/sunos-x64@0.20.2: + resolution: {integrity: sha512-2UyFtRC6cXLyejf/YEld4Hajo7UHILetzE1vsRcGL3earZEW77JxrFjH4Ez2qaTiEfMgAXxfAZCm1fvM/G/o8w==} + engines: {node: '>=12'} + cpu: [x64] + os: [sunos] + requiresBuild: true + dev: false + optional: true + + /@esbuild/win32-arm64@0.20.2: + resolution: {integrity: sha512-GRibxoawM9ZCnDxnP3usoUDO9vUkpAxIIZ6GQI+IlVmr5kP3zUq+l17xELTHMWTWzjxa2guPNyrpq1GWmPvcGQ==} + engines: {node: '>=12'} + cpu: [arm64] + os: [win32] + requiresBuild: true + dev: false + optional: true + + /@esbuild/win32-ia32@0.20.2: + resolution: {integrity: sha512-HfLOfn9YWmkSKRQqovpnITazdtquEW8/SoHW7pWpuEeguaZI4QnCRW6b+oZTztdBnZOS2hqJ6im/D5cPzBTTlQ==} + engines: {node: '>=12'} + cpu: [ia32] + os: [win32] + requiresBuild: true + dev: false + optional: true + + /@esbuild/win32-x64@0.20.2: + resolution: {integrity: sha512-N49X4lJX27+l9jbLKSqZ6bKNjzQvHaT8IIFUy+YIqmXQdjYCToGWwOItDrfby14c78aDd5NHQl29xingXfCdLQ==} + engines: {node: '>=12'} + cpu: [x64] + os: [win32] + requiresBuild: true + dev: false + optional: true + /@ethereumjs/rlp@4.0.1: resolution: {integrity: sha512-tqsQiBQDQdmPWE1xkkBq4rlSW5QZpLOUJ5RJh2/9fug+q9tnUhuZoVLk7s0scUIKTOzEtR72DFBXI4WiZcMpvw==} engines: {node: '>=14'} @@ -431,6 +641,10 @@ packages: - utf-8-validate dev: false + /@jridgewell/sourcemap-codec@1.4.15: + resolution: {integrity: sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==} + dev: false + /@metaplex-foundation/beet-solana@0.3.1: resolution: {integrity: sha512-tgyEl6dvtLln8XX81JyBvWjIiEcjTkUwZbrM5dIobTmoqMuGewSyk9CClno8qsMsFdB5T3jC91Rjeqmu/6xk2g==} dependencies: @@ -644,6 +858,37 @@ packages: - utf-8-validate dev: false + /@multiplechain/solana-walletconnect@0.1.1(@solana/web3.js@1.91.8)(vite@5.2.11): + resolution: {integrity: sha512-WEqxfzgZj+qjCikuOZG5UC6Kdro0UavagiZ+vzvJ19dKoIf97oY46B92jPkXQbAeWHDB1yJusJBRUJpfHt1qqQ==} + dependencies: + '@solana/wallet-adapter-base': 0.9.23(@solana/web3.js@1.91.8) + '@walletconnect/qrcode-modal': 1.8.0 + '@walletconnect/sign-client': 2.13.0 + '@walletconnect/utils': 2.13.0 + vite-plugin-node-polyfills: 0.21.0(vite@5.2.11) + transitivePeerDependencies: + - '@azure/app-configuration' + - '@azure/cosmos' + - '@azure/data-tables' + - '@azure/identity' + - '@azure/keyvault-secrets' + - '@azure/storage-blob' + - '@capacitor/preferences' + - '@netlify/blobs' + - '@planetscale/database' + - '@react-native-async-storage/async-storage' + - '@solana/web3.js' + - '@upstash/redis' + - '@vercel/kv' + - bufferutil + - encoding + - ioredis + - rollup + - uWebSockets.js + - utf-8-validate + - vite + dev: false + /@multiplechain/types@0.1.56: resolution: {integrity: sha512-tnkgDwW0AWxEfhE/392LR6ZPE7Pxz5/Ei1XYsQISGkOfYYZrsvJXr69fXTjDOHCq7RCuQqytKmhnKs5K4xHd7w==} dev: false @@ -814,6 +1059,147 @@ packages: engines: {node: '>= 16'} dev: false + /@parcel/watcher-android-arm64@2.4.1: + resolution: {integrity: sha512-LOi/WTbbh3aTn2RYddrO8pnapixAziFl6SMxHM69r3tvdSm94JtCenaKgk1GRg5FJ5wpMCpHeW+7yqPlvZv7kg==} + engines: {node: '>= 10.0.0'} + cpu: [arm64] + os: [android] + requiresBuild: true + dev: false + optional: true + + /@parcel/watcher-darwin-arm64@2.4.1: + resolution: {integrity: sha512-ln41eihm5YXIY043vBrrHfn94SIBlqOWmoROhsMVTSXGh0QahKGy77tfEywQ7v3NywyxBBkGIfrWRHm0hsKtzA==} + engines: {node: '>= 10.0.0'} + cpu: [arm64] + os: [darwin] + requiresBuild: true + dev: false + optional: true + + /@parcel/watcher-darwin-x64@2.4.1: + resolution: {integrity: sha512-yrw81BRLjjtHyDu7J61oPuSoeYWR3lDElcPGJyOvIXmor6DEo7/G2u1o7I38cwlcoBHQFULqF6nesIX3tsEXMg==} + engines: {node: '>= 10.0.0'} + cpu: [x64] + os: [darwin] + requiresBuild: true + dev: false + optional: true + + /@parcel/watcher-freebsd-x64@2.4.1: + resolution: {integrity: sha512-TJa3Pex/gX3CWIx/Co8k+ykNdDCLx+TuZj3f3h7eOjgpdKM+Mnix37RYsYU4LHhiYJz3DK5nFCCra81p6g050w==} + engines: {node: '>= 10.0.0'} + cpu: [x64] + os: [freebsd] + requiresBuild: true + dev: false + optional: true + + /@parcel/watcher-linux-arm-glibc@2.4.1: + resolution: {integrity: sha512-4rVYDlsMEYfa537BRXxJ5UF4ddNwnr2/1O4MHM5PjI9cvV2qymvhwZSFgXqbS8YoTk5i/JR0L0JDs69BUn45YA==} + engines: {node: '>= 10.0.0'} + cpu: [arm] + os: [linux] + requiresBuild: true + dev: false + optional: true + + /@parcel/watcher-linux-arm64-glibc@2.4.1: + resolution: {integrity: sha512-BJ7mH985OADVLpbrzCLgrJ3TOpiZggE9FMblfO65PlOCdG++xJpKUJ0Aol74ZUIYfb8WsRlUdgrZxKkz3zXWYA==} + engines: {node: '>= 10.0.0'} + cpu: [arm64] + os: [linux] + requiresBuild: true + dev: false + optional: true + + /@parcel/watcher-linux-arm64-musl@2.4.1: + resolution: {integrity: sha512-p4Xb7JGq3MLgAfYhslU2SjoV9G0kI0Xry0kuxeG/41UfpjHGOhv7UoUDAz/jb1u2elbhazy4rRBL8PegPJFBhA==} + engines: {node: '>= 10.0.0'} + cpu: [arm64] + os: [linux] + requiresBuild: true + dev: false + optional: true + + /@parcel/watcher-linux-x64-glibc@2.4.1: + resolution: {integrity: sha512-s9O3fByZ/2pyYDPoLM6zt92yu6P4E39a03zvO0qCHOTjxmt3GHRMLuRZEWhWLASTMSrrnVNWdVI/+pUElJBBBg==} + engines: {node: '>= 10.0.0'} + cpu: [x64] + os: [linux] + requiresBuild: true + dev: false + optional: true + + /@parcel/watcher-linux-x64-musl@2.4.1: + resolution: {integrity: sha512-L2nZTYR1myLNST0O632g0Dx9LyMNHrn6TOt76sYxWLdff3cB22/GZX2UPtJnaqQPdCRoszoY5rcOj4oMTtp5fQ==} + engines: {node: '>= 10.0.0'} + cpu: [x64] + os: [linux] + requiresBuild: true + dev: false + optional: true + + /@parcel/watcher-wasm@2.4.1: + resolution: {integrity: sha512-/ZR0RxqxU/xxDGzbzosMjh4W6NdYFMqq2nvo2b8SLi7rsl/4jkL8S5stIikorNkdR50oVDvqb/3JT05WM+CRRA==} + engines: {node: '>= 10.0.0'} + dependencies: + is-glob: 4.0.3 + micromatch: 4.0.6 + dev: false + bundledDependencies: + - napi-wasm + + /@parcel/watcher-win32-arm64@2.4.1: + resolution: {integrity: sha512-Uq2BPp5GWhrq/lcuItCHoqxjULU1QYEcyjSO5jqqOK8RNFDBQnenMMx4gAl3v8GiWa59E9+uDM7yZ6LxwUIfRg==} + engines: {node: '>= 10.0.0'} + cpu: [arm64] + os: [win32] + requiresBuild: true + dev: false + optional: true + + /@parcel/watcher-win32-ia32@2.4.1: + resolution: {integrity: sha512-maNRit5QQV2kgHFSYwftmPBxiuK5u4DXjbXx7q6eKjq5dsLXZ4FJiVvlcw35QXzk0KrUecJmuVFbj4uV9oYrcw==} + engines: {node: '>= 10.0.0'} + cpu: [ia32] + os: [win32] + requiresBuild: true + dev: false + optional: true + + /@parcel/watcher-win32-x64@2.4.1: + resolution: {integrity: sha512-+DvS92F9ezicfswqrvIRM2njcYJbd5mb9CUgtrHCHmvn7pPPa+nMDRu1o1bYYz/l5IB2NVGNJWiH7h1E58IF2A==} + engines: {node: '>= 10.0.0'} + cpu: [x64] + os: [win32] + requiresBuild: true + dev: false + optional: true + + /@parcel/watcher@2.4.1: + resolution: {integrity: sha512-HNjmfLQEVRZmHRET336f20H/8kOozUGwk7yajvsonjNxbj2wBTK1WsQuHkD5yYh9RxFGL2EyDHryOihOwUoKDA==} + engines: {node: '>= 10.0.0'} + dependencies: + detect-libc: 1.0.3 + is-glob: 4.0.3 + micromatch: 4.0.6 + node-addon-api: 7.1.0 + optionalDependencies: + '@parcel/watcher-android-arm64': 2.4.1 + '@parcel/watcher-darwin-arm64': 2.4.1 + '@parcel/watcher-darwin-x64': 2.4.1 + '@parcel/watcher-freebsd-x64': 2.4.1 + '@parcel/watcher-linux-arm-glibc': 2.4.1 + '@parcel/watcher-linux-arm64-glibc': 2.4.1 + '@parcel/watcher-linux-arm64-musl': 2.4.1 + '@parcel/watcher-linux-x64-glibc': 2.4.1 + '@parcel/watcher-linux-x64-musl': 2.4.1 + '@parcel/watcher-win32-arm64': 2.4.1 + '@parcel/watcher-win32-ia32': 2.4.1 + '@parcel/watcher-win32-x64': 2.4.1 + dev: false + /@randlabs/communication-bridge@1.0.1: resolution: {integrity: sha512-CzS0U8IFfXNK7QaJFE4pjbxDGfPjbXBEsEaCn9FN15F+ouSAEUQkva3Gl66hrkBZOGexKFEWMwUHIDKpZ2hfVg==} requiresBuild: true @@ -828,6 +1214,162 @@ packages: dev: false optional: true + /@rollup/plugin-inject@5.0.5: + resolution: {integrity: sha512-2+DEJbNBoPROPkgTDNe8/1YXWcqxbN5DTjASVIOx8HS+pITXushyNiBV56RB08zuptzz8gT3YfkqriTBVycepg==} + engines: {node: '>=14.0.0'} + peerDependencies: + rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0 + peerDependenciesMeta: + rollup: + optional: true + dependencies: + '@rollup/pluginutils': 5.1.0 + estree-walker: 2.0.2 + magic-string: 0.30.10 + dev: false + + /@rollup/pluginutils@5.1.0: + resolution: {integrity: sha512-XTIWOPPcpvyKI6L1NHo0lFlCyznUEyPmPY1mc3KpPVDYulHSTvyeLNVW00QTLIAFNhR3kYnJTQHeGqU4M3n09g==} + engines: {node: '>=14.0.0'} + peerDependencies: + rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0 + peerDependenciesMeta: + rollup: + optional: true + dependencies: + '@types/estree': 1.0.5 + estree-walker: 2.0.2 + picomatch: 2.3.1 + dev: false + + /@rollup/rollup-android-arm-eabi@4.17.2: + resolution: {integrity: sha512-NM0jFxY8bB8QLkoKxIQeObCaDlJKewVlIEkuyYKm5An1tdVZ966w2+MPQ2l8LBZLjR+SgyV+nRkTIunzOYBMLQ==} + cpu: [arm] + os: [android] + requiresBuild: true + dev: false + optional: true + + /@rollup/rollup-android-arm64@4.17.2: + resolution: {integrity: sha512-yeX/Usk7daNIVwkq2uGoq2BYJKZY1JfyLTaHO/jaiSwi/lsf8fTFoQW/n6IdAsx5tx+iotu2zCJwz8MxI6D/Bw==} + cpu: [arm64] + os: [android] + requiresBuild: true + dev: false + optional: true + + /@rollup/rollup-darwin-arm64@4.17.2: + resolution: {integrity: sha512-kcMLpE6uCwls023+kknm71ug7MZOrtXo+y5p/tsg6jltpDtgQY1Eq5sGfHcQfb+lfuKwhBmEURDga9N0ol4YPw==} + cpu: [arm64] + os: [darwin] + requiresBuild: true + dev: false + optional: true + + /@rollup/rollup-darwin-x64@4.17.2: + resolution: {integrity: sha512-AtKwD0VEx0zWkL0ZjixEkp5tbNLzX+FCqGG1SvOu993HnSz4qDI6S4kGzubrEJAljpVkhRSlg5bzpV//E6ysTQ==} + cpu: [x64] + os: [darwin] + requiresBuild: true + dev: false + optional: true + + /@rollup/rollup-linux-arm-gnueabihf@4.17.2: + resolution: {integrity: sha512-3reX2fUHqN7sffBNqmEyMQVj/CKhIHZd4y631duy0hZqI8Qoqf6lTtmAKvJFYa6bhU95B1D0WgzHkmTg33In0A==} + cpu: [arm] + os: [linux] + requiresBuild: true + dev: false + optional: true + + /@rollup/rollup-linux-arm-musleabihf@4.17.2: + resolution: {integrity: sha512-uSqpsp91mheRgw96xtyAGP9FW5ChctTFEoXP0r5FAzj/3ZRv3Uxjtc7taRQSaQM/q85KEKjKsZuiZM3GyUivRg==} + cpu: [arm] + os: [linux] + requiresBuild: true + dev: false + optional: true + + /@rollup/rollup-linux-arm64-gnu@4.17.2: + resolution: {integrity: sha512-EMMPHkiCRtE8Wdk3Qhtciq6BndLtstqZIroHiiGzB3C5LDJmIZcSzVtLRbwuXuUft1Cnv+9fxuDtDxz3k3EW2A==} + cpu: [arm64] + os: [linux] + requiresBuild: true + dev: false + optional: true + + /@rollup/rollup-linux-arm64-musl@4.17.2: + resolution: {integrity: sha512-NMPylUUZ1i0z/xJUIx6VUhISZDRT+uTWpBcjdv0/zkp7b/bQDF+NfnfdzuTiB1G6HTodgoFa93hp0O1xl+/UbA==} + cpu: [arm64] + os: [linux] + requiresBuild: true + dev: false + optional: true + + /@rollup/rollup-linux-powerpc64le-gnu@4.17.2: + resolution: {integrity: sha512-T19My13y8uYXPw/L/k0JYaX1fJKFT/PWdXiHr8mTbXWxjVF1t+8Xl31DgBBvEKclw+1b00Chg0hxE2O7bTG7GQ==} + cpu: [ppc64] + os: [linux] + requiresBuild: true + dev: false + optional: true + + /@rollup/rollup-linux-riscv64-gnu@4.17.2: + resolution: {integrity: sha512-BOaNfthf3X3fOWAB+IJ9kxTgPmMqPPH5f5k2DcCsRrBIbWnaJCgX2ll77dV1TdSy9SaXTR5iDXRL8n7AnoP5cg==} + cpu: [riscv64] + os: [linux] + requiresBuild: true + dev: false + optional: true + + /@rollup/rollup-linux-s390x-gnu@4.17.2: + resolution: {integrity: sha512-W0UP/x7bnn3xN2eYMql2T/+wpASLE5SjObXILTMPUBDB/Fg/FxC+gX4nvCfPBCbNhz51C+HcqQp2qQ4u25ok6g==} + cpu: [s390x] + os: [linux] + requiresBuild: true + dev: false + optional: true + + /@rollup/rollup-linux-x64-gnu@4.17.2: + resolution: {integrity: sha512-Hy7pLwByUOuyaFC6mAr7m+oMC+V7qyifzs/nW2OJfC8H4hbCzOX07Ov0VFk/zP3kBsELWNFi7rJtgbKYsav9QQ==} + cpu: [x64] + os: [linux] + requiresBuild: true + dev: false + optional: true + + /@rollup/rollup-linux-x64-musl@4.17.2: + resolution: {integrity: sha512-h1+yTWeYbRdAyJ/jMiVw0l6fOOm/0D1vNLui9iPuqgRGnXA0u21gAqOyB5iHjlM9MMfNOm9RHCQ7zLIzT0x11Q==} + cpu: [x64] + os: [linux] + requiresBuild: true + dev: false + optional: true + + /@rollup/rollup-win32-arm64-msvc@4.17.2: + resolution: {integrity: sha512-tmdtXMfKAjy5+IQsVtDiCfqbynAQE/TQRpWdVataHmhMb9DCoJxp9vLcCBjEQWMiUYxO1QprH/HbY9ragCEFLA==} + cpu: [arm64] + os: [win32] + requiresBuild: true + dev: false + optional: true + + /@rollup/rollup-win32-ia32-msvc@4.17.2: + resolution: {integrity: sha512-7II/QCSTAHuE5vdZaQEwJq2ZACkBpQDOmQsE6D6XUbnBHW8IAhm4eTufL6msLJorzrHDFv3CF8oCA/hSIRuZeQ==} + cpu: [ia32] + os: [win32] + requiresBuild: true + dev: false + optional: true + + /@rollup/rollup-win32-x64-msvc@4.17.2: + resolution: {integrity: sha512-TGGO7v7qOq4CYmSBVEYpI1Y5xDuCEnbVC5Vth8mOsW0gDSzxNrVERPc790IGHsrT2dQSimgMr9Ub3Y1Jci5/8w==} + cpu: [x64] + os: [win32] + requiresBuild: true + dev: false + optional: true + /@scure/base@1.1.6: resolution: {integrity: sha512-ok9AWwhcgYuGG3Zfhyqg+zwl+Wn5uE+dwC0NV/2qQkx4dABbb/bx96vWu8NSj+BNjjSjno+JRYRjle1jV08k3g==} dev: false @@ -1192,18 +1734,138 @@ packages: uuid: 9.0.1 dev: false - /@supercharge/promise-pool@3.2.0: - resolution: {integrity: sha512-pj0cAALblTZBPtMltWOlZTQSLT07jIaFNeM8TWoJD1cQMgDB9mcMlVMoetiB35OzNJpqQ2b+QEtwiR9f20mADg==} - engines: {node: '>=8'} + /@stablelib/aead@1.0.1: + resolution: {integrity: sha512-q39ik6sxGHewqtO0nP4BuSe3db5G1fEJE8ukvngS2gLkBXyy6E7pLubhbYgnkDFv6V8cWaxcE4Xn0t6LWcJkyg==} dev: false - /@types/connect@3.4.38: - resolution: {integrity: sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==} + /@stablelib/binary@1.0.1: + resolution: {integrity: sha512-ClJWvmL6UBM/wjkvv/7m5VP3GMr9t0osr4yVgLZsLCOz4hGN9gIAFEqnJ0TsSMAN+n840nf2cHZnA5/KFqHC7Q==} dependencies: - '@types/node': 20.12.7 + '@stablelib/int': 1.0.1 dev: false - /@types/node@11.11.6: + /@stablelib/bytes@1.0.1: + resolution: {integrity: sha512-Kre4Y4kdwuqL8BR2E9hV/R5sOrUj6NanZaZis0V6lX5yzqC3hBuVSDXUIBqQv/sCpmuWRiHLwqiT1pqqjuBXoQ==} + dev: false + + /@stablelib/chacha20poly1305@1.0.1: + resolution: {integrity: sha512-MmViqnqHd1ymwjOQfghRKw2R/jMIGT3wySN7cthjXCBdO+qErNPUBnRzqNpnvIwg7JBCg3LdeCZZO4de/yEhVA==} + dependencies: + '@stablelib/aead': 1.0.1 + '@stablelib/binary': 1.0.1 + '@stablelib/chacha': 1.0.1 + '@stablelib/constant-time': 1.0.1 + '@stablelib/poly1305': 1.0.1 + '@stablelib/wipe': 1.0.1 + dev: false + + /@stablelib/chacha@1.0.1: + resolution: {integrity: sha512-Pmlrswzr0pBzDofdFuVe1q7KdsHKhhU24e8gkEwnTGOmlC7PADzLVxGdn2PoNVBBabdg0l/IfLKg6sHAbTQugg==} + dependencies: + '@stablelib/binary': 1.0.1 + '@stablelib/wipe': 1.0.1 + dev: false + + /@stablelib/constant-time@1.0.1: + resolution: {integrity: sha512-tNOs3uD0vSJcK6z1fvef4Y+buN7DXhzHDPqRLSXUel1UfqMB1PWNsnnAezrKfEwTLpN0cGH2p9NNjs6IqeD0eg==} + dev: false + + /@stablelib/ed25519@1.0.3: + resolution: {integrity: sha512-puIMWaX9QlRsbhxfDc5i+mNPMY+0TmQEskunY1rZEBPi1acBCVQAhnsk/1Hk50DGPtVsZtAWQg4NHGlVaO9Hqg==} + dependencies: + '@stablelib/random': 1.0.2 + '@stablelib/sha512': 1.0.1 + '@stablelib/wipe': 1.0.1 + dev: false + + /@stablelib/hash@1.0.1: + resolution: {integrity: sha512-eTPJc/stDkdtOcrNMZ6mcMK1e6yBbqRBaNW55XA1jU8w/7QdnCF0CmMmOD1m7VSkBR44PWrMHU2l6r8YEQHMgg==} + dev: false + + /@stablelib/hkdf@1.0.1: + resolution: {integrity: sha512-SBEHYE16ZXlHuaW5RcGk533YlBj4grMeg5TooN80W3NpcHRtLZLLXvKyX0qcRFxf+BGDobJLnwkvgEwHIDBR6g==} + dependencies: + '@stablelib/hash': 1.0.1 + '@stablelib/hmac': 1.0.1 + '@stablelib/wipe': 1.0.1 + dev: false + + /@stablelib/hmac@1.0.1: + resolution: {integrity: sha512-V2APD9NSnhVpV/QMYgCVMIYKiYG6LSqw1S65wxVoirhU/51ACio6D4yDVSwMzuTJXWZoVHbDdINioBwKy5kVmA==} + dependencies: + '@stablelib/constant-time': 1.0.1 + '@stablelib/hash': 1.0.1 + '@stablelib/wipe': 1.0.1 + dev: false + + /@stablelib/int@1.0.1: + resolution: {integrity: sha512-byr69X/sDtDiIjIV6m4roLVWnNNlRGzsvxw+agj8CIEazqWGOQp2dTYgQhtyVXV9wpO6WyXRQUzLV/JRNumT2w==} + dev: false + + /@stablelib/keyagreement@1.0.1: + resolution: {integrity: sha512-VKL6xBwgJnI6l1jKrBAfn265cspaWBPAPEc62VBQrWHLqVgNRE09gQ/AnOEyKUWrrqfD+xSQ3u42gJjLDdMDQg==} + dependencies: + '@stablelib/bytes': 1.0.1 + dev: false + + /@stablelib/poly1305@1.0.1: + resolution: {integrity: sha512-1HlG3oTSuQDOhSnLwJRKeTRSAdFNVB/1djy2ZbS35rBSJ/PFqx9cf9qatinWghC2UbfOYD8AcrtbUQl8WoxabA==} + dependencies: + '@stablelib/constant-time': 1.0.1 + '@stablelib/wipe': 1.0.1 + dev: false + + /@stablelib/random@1.0.2: + resolution: {integrity: sha512-rIsE83Xpb7clHPVRlBj8qNe5L8ISQOzjghYQm/dZ7VaM2KHYwMW5adjQjrzTZCchFnNCNhkwtnOBa9HTMJCI8w==} + dependencies: + '@stablelib/binary': 1.0.1 + '@stablelib/wipe': 1.0.1 + dev: false + + /@stablelib/sha256@1.0.1: + resolution: {integrity: sha512-GIIH3e6KH+91FqGV42Kcj71Uefd/QEe7Dy42sBTeqppXV95ggCcxLTk39bEr+lZfJmp+ghsR07J++ORkRELsBQ==} + dependencies: + '@stablelib/binary': 1.0.1 + '@stablelib/hash': 1.0.1 + '@stablelib/wipe': 1.0.1 + dev: false + + /@stablelib/sha512@1.0.1: + resolution: {integrity: sha512-13gl/iawHV9zvDKciLo1fQ8Bgn2Pvf7OV6amaRVKiq3pjQ3UmEpXxWiAfV8tYjUpeZroBxtyrwtdooQT/i3hzw==} + dependencies: + '@stablelib/binary': 1.0.1 + '@stablelib/hash': 1.0.1 + '@stablelib/wipe': 1.0.1 + dev: false + + /@stablelib/wipe@1.0.1: + resolution: {integrity: sha512-WfqfX/eXGiAd3RJe4VU2snh/ZPwtSjLG4ynQ/vYzvghTh7dHFcI1wl+nrkWG6lGhukOxOsUHfv8dUXr58D0ayg==} + dev: false + + /@stablelib/x25519@1.0.3: + resolution: {integrity: sha512-KnTbKmUhPhHavzobclVJQG5kuivH+qDLpe84iRqX3CLrKp881cF160JvXJ+hjn1aMyCwYOKeIZefIH/P5cJoRw==} + dependencies: + '@stablelib/keyagreement': 1.0.1 + '@stablelib/random': 1.0.2 + '@stablelib/wipe': 1.0.1 + dev: false + + /@supercharge/promise-pool@3.2.0: + resolution: {integrity: sha512-pj0cAALblTZBPtMltWOlZTQSLT07jIaFNeM8TWoJD1cQMgDB9mcMlVMoetiB35OzNJpqQ2b+QEtwiR9f20mADg==} + engines: {node: '>=8'} + dev: false + + /@types/connect@3.4.38: + resolution: {integrity: sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==} + dependencies: + '@types/node': 20.12.7 + dev: false + + /@types/estree@1.0.5: + resolution: {integrity: sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==} + dev: false + + /@types/node@11.11.6: resolution: {integrity: sha512-Exw4yUWMBXM3X+8oqzJNRqZSwUAaS4+7NdvHqQuFi/d+synz++xmX3QIf+BFqneW8N31R8Ky+sikfZUXq07ggQ==} dev: false @@ -1248,6 +1910,316 @@ packages: '@wallet-standard/base': 1.0.1 dev: false + /@walletconnect/browser-utils@1.8.0: + resolution: {integrity: sha512-Wcqqx+wjxIo9fv6eBUFHPsW1y/bGWWRboni5dfD8PtOmrihrEpOCmvRJe4rfl7xgJW8Ea9UqKEaq0bIRLHlK4A==} + dependencies: + '@walletconnect/safe-json': 1.0.0 + '@walletconnect/types': 1.8.0 + '@walletconnect/window-getters': 1.0.0 + '@walletconnect/window-metadata': 1.0.0 + detect-browser: 5.2.0 + dev: false + + /@walletconnect/core@2.13.0: + resolution: {integrity: sha512-blDuZxQenjeXcVJvHxPznTNl6c/2DO4VNrFnus+qHmO6OtT5lZRowdMtlCaCNb1q0OxzgrmBDcTOCbFcCpio/g==} + dependencies: + '@walletconnect/heartbeat': 1.2.2 + '@walletconnect/jsonrpc-provider': 1.0.14 + '@walletconnect/jsonrpc-types': 1.0.4 + '@walletconnect/jsonrpc-utils': 1.0.8 + '@walletconnect/jsonrpc-ws-connection': 1.0.14 + '@walletconnect/keyvaluestorage': 1.1.1 + '@walletconnect/logger': 2.1.2 + '@walletconnect/relay-api': 1.0.10 + '@walletconnect/relay-auth': 1.0.4 + '@walletconnect/safe-json': 1.0.2 + '@walletconnect/time': 1.0.2 + '@walletconnect/types': 2.13.0 + '@walletconnect/utils': 2.13.0 + events: 3.3.0 + isomorphic-unfetch: 3.1.0 + lodash.isequal: 4.5.0 + uint8arrays: 3.1.0 + transitivePeerDependencies: + - '@azure/app-configuration' + - '@azure/cosmos' + - '@azure/data-tables' + - '@azure/identity' + - '@azure/keyvault-secrets' + - '@azure/storage-blob' + - '@capacitor/preferences' + - '@netlify/blobs' + - '@planetscale/database' + - '@react-native-async-storage/async-storage' + - '@upstash/redis' + - '@vercel/kv' + - bufferutil + - encoding + - ioredis + - uWebSockets.js + - utf-8-validate + dev: false + + /@walletconnect/environment@1.0.1: + resolution: {integrity: sha512-T426LLZtHj8e8rYnKfzsw1aG6+M0BT1ZxayMdv/p8yM0MU+eJDISqNY3/bccxRr4LrF9csq02Rhqt08Ibl0VRg==} + dependencies: + tslib: 1.14.1 + dev: false + + /@walletconnect/events@1.0.1: + resolution: {integrity: sha512-NPTqaoi0oPBVNuLv7qPaJazmGHs5JGyO8eEAk5VGKmJzDR7AHzD4k6ilox5kxk1iwiOnFopBOOMLs86Oa76HpQ==} + dependencies: + keyvaluestorage-interface: 1.0.0 + tslib: 1.14.1 + dev: false + + /@walletconnect/heartbeat@1.2.2: + resolution: {integrity: sha512-uASiRmC5MwhuRuf05vq4AT48Pq8RMi876zV8rr8cV969uTOzWdB/k+Lj5yI2PBtB1bGQisGen7MM1GcZlQTBXw==} + dependencies: + '@walletconnect/events': 1.0.1 + '@walletconnect/time': 1.0.2 + events: 3.3.0 + dev: false + + /@walletconnect/jsonrpc-provider@1.0.14: + resolution: {integrity: sha512-rtsNY1XqHvWj0EtITNeuf8PHMvlCLiS3EjQL+WOkxEOA4KPxsohFnBDeyPYiNm4ZvkQdLnece36opYidmtbmow==} + dependencies: + '@walletconnect/jsonrpc-utils': 1.0.8 + '@walletconnect/safe-json': 1.0.2 + events: 3.3.0 + dev: false + + /@walletconnect/jsonrpc-types@1.0.4: + resolution: {integrity: sha512-P6679fG/M+wuWg9TY8mh6xFSdYnFyFjwFelxyISxMDrlbXokorEVXYOxiqEbrU3x1BmBoCAJJ+vtEaEoMlpCBQ==} + dependencies: + events: 3.3.0 + keyvaluestorage-interface: 1.0.0 + dev: false + + /@walletconnect/jsonrpc-utils@1.0.8: + resolution: {integrity: sha512-vdeb03bD8VzJUL6ZtzRYsFMq1eZQcM3EAzT0a3st59dyLfJ0wq+tKMpmGH7HlB7waD858UWgfIcudbPFsbzVdw==} + dependencies: + '@walletconnect/environment': 1.0.1 + '@walletconnect/jsonrpc-types': 1.0.4 + tslib: 1.14.1 + dev: false + + /@walletconnect/jsonrpc-ws-connection@1.0.14: + resolution: {integrity: sha512-Jsl6fC55AYcbkNVkwNM6Jo+ufsuCQRqViOQ8ZBPH9pRREHH9welbBiszuTLqEJiQcO/6XfFDl6bzCJIkrEi8XA==} + dependencies: + '@walletconnect/jsonrpc-utils': 1.0.8 + '@walletconnect/safe-json': 1.0.2 + events: 3.3.0 + ws: 7.5.9 + transitivePeerDependencies: + - bufferutil + - utf-8-validate + dev: false + + /@walletconnect/keyvaluestorage@1.1.1: + resolution: {integrity: sha512-V7ZQq2+mSxAq7MrRqDxanTzu2RcElfK1PfNYiaVnJgJ7Q7G7hTVwF8voIBx92qsRyGHZihrwNPHuZd1aKkd0rA==} + peerDependencies: + '@react-native-async-storage/async-storage': 1.x + peerDependenciesMeta: + '@react-native-async-storage/async-storage': + optional: true + dependencies: + '@walletconnect/safe-json': 1.0.2 + idb-keyval: 6.2.1 + unstorage: 1.10.2(idb-keyval@6.2.1) + transitivePeerDependencies: + - '@azure/app-configuration' + - '@azure/cosmos' + - '@azure/data-tables' + - '@azure/identity' + - '@azure/keyvault-secrets' + - '@azure/storage-blob' + - '@capacitor/preferences' + - '@netlify/blobs' + - '@planetscale/database' + - '@upstash/redis' + - '@vercel/kv' + - ioredis + - uWebSockets.js + dev: false + + /@walletconnect/logger@2.1.2: + resolution: {integrity: sha512-aAb28I3S6pYXZHQm5ESB+V6rDqIYfsnHaQyzFbwUUBFY4H0OXx/YtTl8lvhUNhMMfb9UxbwEBS253TlXUYJWSw==} + dependencies: + '@walletconnect/safe-json': 1.0.2 + pino: 7.11.0 + dev: false + + /@walletconnect/mobile-registry@1.4.0: + resolution: {integrity: sha512-ZtKRio4uCZ1JUF7LIdecmZt7FOLnX72RPSY7aUVu7mj7CSfxDwUn6gBuK6WGtH+NZCldBqDl5DenI5fFSvkKYw==} + deprecated: 'Deprecated in favor of dynamic registry available from: https://github.com/walletconnect/walletconnect-registry' + dev: false + + /@walletconnect/qrcode-modal@1.8.0: + resolution: {integrity: sha512-BueaFefaAi8mawE45eUtztg3ZFbsAH4DDXh1UNwdUlsvFMjqcYzLUG0xZvDd6z2eOpbgDg2N3bl6gF0KONj1dg==} + deprecated: 'WalletConnect''s v1 SDKs are now deprecated. Please upgrade to a v2 SDK. For details see: https://docs.walletconnect.com/' + dependencies: + '@walletconnect/browser-utils': 1.8.0 + '@walletconnect/mobile-registry': 1.4.0 + '@walletconnect/types': 1.8.0 + copy-to-clipboard: 3.3.3 + preact: 10.4.1 + qrcode: 1.4.4 + dev: false + + /@walletconnect/relay-api@1.0.10: + resolution: {integrity: sha512-tqrdd4zU9VBNqUaXXQASaexklv6A54yEyQQEXYOCr+Jz8Ket0dmPBDyg19LVSNUN2cipAghQc45/KVmfFJ0cYw==} + dependencies: + '@walletconnect/jsonrpc-types': 1.0.4 + dev: false + + /@walletconnect/relay-auth@1.0.4: + resolution: {integrity: sha512-kKJcS6+WxYq5kshpPaxGHdwf5y98ZwbfuS4EE/NkQzqrDFm5Cj+dP8LofzWvjrrLkZq7Afy7WrQMXdLy8Sx7HQ==} + dependencies: + '@stablelib/ed25519': 1.0.3 + '@stablelib/random': 1.0.2 + '@walletconnect/safe-json': 1.0.2 + '@walletconnect/time': 1.0.2 + tslib: 1.14.1 + uint8arrays: 3.1.0 + dev: false + + /@walletconnect/safe-json@1.0.0: + resolution: {integrity: sha512-QJzp/S/86sUAgWY6eh5MKYmSfZaRpIlmCJdi5uG4DJlKkZrHEF7ye7gA+VtbVzvTtpM/gRwO2plQuiooIeXjfg==} + dev: false + + /@walletconnect/safe-json@1.0.2: + resolution: {integrity: sha512-Ogb7I27kZ3LPC3ibn8ldyUr5544t3/STow9+lzz7Sfo808YD7SBWk7SAsdBFlYgP2zDRy2hS3sKRcuSRM0OTmA==} + dependencies: + tslib: 1.14.1 + dev: false + + /@walletconnect/sign-client@2.13.0: + resolution: {integrity: sha512-En7KSvNUlQFx20IsYGsFgkNJ2lpvDvRsSFOT5PTdGskwCkUfOpB33SQJ6nCrN19gyoKPNvWg80Cy6MJI0TjNYA==} + dependencies: + '@walletconnect/core': 2.13.0 + '@walletconnect/events': 1.0.1 + '@walletconnect/heartbeat': 1.2.2 + '@walletconnect/jsonrpc-utils': 1.0.8 + '@walletconnect/logger': 2.1.2 + '@walletconnect/time': 1.0.2 + '@walletconnect/types': 2.13.0 + '@walletconnect/utils': 2.13.0 + events: 3.3.0 + transitivePeerDependencies: + - '@azure/app-configuration' + - '@azure/cosmos' + - '@azure/data-tables' + - '@azure/identity' + - '@azure/keyvault-secrets' + - '@azure/storage-blob' + - '@capacitor/preferences' + - '@netlify/blobs' + - '@planetscale/database' + - '@react-native-async-storage/async-storage' + - '@upstash/redis' + - '@vercel/kv' + - bufferutil + - encoding + - ioredis + - uWebSockets.js + - utf-8-validate + dev: false + + /@walletconnect/time@1.0.2: + resolution: {integrity: sha512-uzdd9woDcJ1AaBZRhqy5rNC9laqWGErfc4dxA9a87mPdKOgWMD85mcFo9dIYIts/Jwocfwn07EC6EzclKubk/g==} + dependencies: + tslib: 1.14.1 + dev: false + + /@walletconnect/types@1.8.0: + resolution: {integrity: sha512-Cn+3I0V0vT9ghMuzh1KzZvCkiAxTq+1TR2eSqw5E5AVWfmCtECFkVZBP6uUJZ8YjwLqXheI+rnjqPy7sVM4Fyg==} + deprecated: 'WalletConnect''s v1 SDKs are now deprecated. Please upgrade to a v2 SDK. For details see: https://docs.walletconnect.com/' + dev: false + + /@walletconnect/types@2.13.0: + resolution: {integrity: sha512-MWaVT0FkZwzYbD3tvk8F+2qpPlz1LUSWHuqbINUtMXnSzJtXN49Y99fR7FuBhNFtDalfuWsEK17GrNA+KnAsPQ==} + dependencies: + '@walletconnect/events': 1.0.1 + '@walletconnect/heartbeat': 1.2.2 + '@walletconnect/jsonrpc-types': 1.0.4 + '@walletconnect/keyvaluestorage': 1.1.1 + '@walletconnect/logger': 2.1.2 + events: 3.3.0 + transitivePeerDependencies: + - '@azure/app-configuration' + - '@azure/cosmos' + - '@azure/data-tables' + - '@azure/identity' + - '@azure/keyvault-secrets' + - '@azure/storage-blob' + - '@capacitor/preferences' + - '@netlify/blobs' + - '@planetscale/database' + - '@react-native-async-storage/async-storage' + - '@upstash/redis' + - '@vercel/kv' + - ioredis + - uWebSockets.js + dev: false + + /@walletconnect/utils@2.13.0: + resolution: {integrity: sha512-q1eDCsRHj5iLe7fF8RroGoPZpdo2CYMZzQSrw1iqL+2+GOeqapxxuJ1vaJkmDUkwgklfB22ufqG6KQnz78sD4w==} + dependencies: + '@stablelib/chacha20poly1305': 1.0.1 + '@stablelib/hkdf': 1.0.1 + '@stablelib/random': 1.0.2 + '@stablelib/sha256': 1.0.1 + '@stablelib/x25519': 1.0.3 + '@walletconnect/relay-api': 1.0.10 + '@walletconnect/safe-json': 1.0.2 + '@walletconnect/time': 1.0.2 + '@walletconnect/types': 2.13.0 + '@walletconnect/window-getters': 1.0.1 + '@walletconnect/window-metadata': 1.0.1 + detect-browser: 5.3.0 + query-string: 7.1.3 + uint8arrays: 3.1.0 + transitivePeerDependencies: + - '@azure/app-configuration' + - '@azure/cosmos' + - '@azure/data-tables' + - '@azure/identity' + - '@azure/keyvault-secrets' + - '@azure/storage-blob' + - '@capacitor/preferences' + - '@netlify/blobs' + - '@planetscale/database' + - '@react-native-async-storage/async-storage' + - '@upstash/redis' + - '@vercel/kv' + - ioredis + - uWebSockets.js + dev: false + + /@walletconnect/window-getters@1.0.0: + resolution: {integrity: sha512-xB0SQsLaleIYIkSsl43vm8EwETpBzJ2gnzk7e0wMF3ktqiTGS6TFHxcprMl5R44KKh4tCcHCJwolMCaDSwtAaA==} + dev: false + + /@walletconnect/window-getters@1.0.1: + resolution: {integrity: sha512-vHp+HqzGxORPAN8gY03qnbTMnhqIwjeRJNOMOAzePRg4xVEEE2WvYsI9G2NMjOknA8hnuYbU3/hwLcKbjhc8+Q==} + dependencies: + tslib: 1.14.1 + dev: false + + /@walletconnect/window-metadata@1.0.0: + resolution: {integrity: sha512-9eFvmJxIKCC3YWOL97SgRkKhlyGXkrHwamfechmqszbypFspaSk+t2jQXAEU7YClHF6Qjw5eYOmy1//zFi9/GA==} + dependencies: + '@walletconnect/window-getters': 1.0.1 + dev: false + + /@walletconnect/window-metadata@1.0.1: + resolution: {integrity: sha512-9koTqyGrM2cqFRW517BPY/iEtUDx2r1+Pwwu5m7sJ7ka79wi3EyqhqcICk/yDmv6jAS1rjKgTKXlEhanYjijcA==} + dependencies: + '@walletconnect/window-getters': 1.0.1 + tslib: 1.14.1 + dev: false + /JSONStream@1.3.5: resolution: {integrity: sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==} hasBin: true @@ -1256,6 +2228,12 @@ packages: through: 2.3.8 dev: false + /acorn@8.11.3: + resolution: {integrity: sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==} + engines: {node: '>=0.4.0'} + hasBin: true + dev: false + /aes-js@3.0.0: resolution: {integrity: sha512-H7wUZRn8WpTq9jocdxQ2c8x2sKo9ZVmzfRE13GiNJXfp7NcKYEdvl3vspKjXox6RIG2VtaRe4JFvxG4rqp2Zuw==} dev: false @@ -1297,11 +2275,23 @@ packages: type-fest: 0.21.3 dev: false + /ansi-regex@4.1.1: + resolution: {integrity: sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==} + engines: {node: '>=6'} + dev: false + /ansi-regex@5.0.1: resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} engines: {node: '>=8'} dev: false + /ansi-styles@3.2.1: + resolution: {integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==} + engines: {node: '>=4'} + dependencies: + color-convert: 1.9.3 + dev: false + /ansi-styles@4.3.0: resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} engines: {node: '>=8'} @@ -1313,6 +2303,14 @@ packages: resolution: {integrity: sha512-QXu7BPrP29VllRxH8GwB7x5iX5qWKAAMLqKQGWTeLWVlNHNOpVMJ91dsxQAIWXpjuW5wqvxu3Jd/nRjrJ+0pqg==} dev: false + /anymatch@3.1.3: + resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} + engines: {node: '>= 8'} + dependencies: + normalize-path: 3.0.0 + picomatch: 2.3.1 + dev: false + /aptos@1.8.5(debug@4.3.4): resolution: {integrity: sha512-iQxliWesNHjGQ5YYXCyss9eg4+bDGQWqAZa73vprqGQ9tungK0cRjUI2fmnp63Ed6UG6rurHrL+b0ckbZAOZZQ==} engines: {node: '>=11.0.0'} @@ -1384,6 +2382,14 @@ packages: dev: false optional: true + /asn1.js@4.10.1: + resolution: {integrity: sha512-p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw==} + dependencies: + bn.js: 4.12.0 + inherits: 2.0.4 + minimalistic-assert: 1.0.1 + dev: false + /asn1.js@5.4.1: resolution: {integrity: sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA==} dependencies: @@ -1393,6 +2399,16 @@ packages: safer-buffer: 2.1.2 dev: false + /assert@2.1.0: + resolution: {integrity: sha512-eLHpSK/Y4nhMJ07gDaAzoX/XAKS8PSaojml3M0DM4JpV1LAi5JOJ/p6H/XWrl8L+DzVEvVCW1z3vWAaB9oTsQw==} + dependencies: + call-bind: 1.0.7 + is-nan: 1.3.2 + object-is: 1.1.6 + object.assign: 4.1.5 + util: 0.12.5 + dev: false + /async-retry@1.3.3: resolution: {integrity: sha512-wfr/jstw9xNi/0teMHrRW7dsz3Lt5ARhYNZ2ewpadnhaIp5mbALhOAP+EAdsC7t4Z6wqsDVv9+W6gm1Dk9mEyw==} dependencies: @@ -1403,6 +2419,11 @@ packages: resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} dev: false + /atomic-sleep@1.0.0: + resolution: {integrity: sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ==} + engines: {node: '>=8.0.0'} + dev: false + /available-typed-arrays@1.0.7: resolution: {integrity: sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==} engines: {node: '>= 0.4'} @@ -1464,6 +2485,11 @@ packages: resolution: {integrity: sha512-2/mKyZH9K85bzOEfhXDBFZTGd1CTs+5IHpeFQo9luiBG7hghdC851Pj2WAhb6E3R6b9tZj/XKhbg4fum+Kepug==} dev: false + /binary-extensions@2.3.0: + resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==} + engines: {node: '>=8'} + dev: false + /bindings@1.5.0: resolution: {integrity: sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==} dependencies: @@ -1514,10 +2540,80 @@ packages: text-encoding-utf-8: 1.0.2 dev: false + /braces@3.0.3: + resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} + engines: {node: '>=8'} + dependencies: + fill-range: 7.1.1 + dev: false + /brorand@1.1.0: resolution: {integrity: sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w==} dev: false + /browser-resolve@2.0.0: + resolution: {integrity: sha512-7sWsQlYL2rGLy2IWm8WL8DCTJvYLc/qlOnsakDac87SOoCd16WLsaAMdCiAqsTNHIe+SXfaqyxyo6THoWqs8WQ==} + dependencies: + resolve: 1.22.8 + dev: false + + /browserify-aes@1.2.0: + resolution: {integrity: sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==} + dependencies: + buffer-xor: 1.0.3 + cipher-base: 1.0.4 + create-hash: 1.2.0 + evp_bytestokey: 1.0.3 + inherits: 2.0.4 + safe-buffer: 5.2.1 + dev: false + + /browserify-cipher@1.0.1: + resolution: {integrity: sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w==} + dependencies: + browserify-aes: 1.2.0 + browserify-des: 1.0.2 + evp_bytestokey: 1.0.3 + dev: false + + /browserify-des@1.0.2: + resolution: {integrity: sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A==} + dependencies: + cipher-base: 1.0.4 + des.js: 1.1.0 + inherits: 2.0.4 + safe-buffer: 5.2.1 + dev: false + + /browserify-rsa@4.1.0: + resolution: {integrity: sha512-AdEER0Hkspgno2aR97SAf6vi0y0k8NuOpGnVH3O99rcA5Q6sh8QxcngtHuJ6uXwnfAXNM4Gn1Gb7/MV1+Ymbog==} + dependencies: + bn.js: 5.2.1 + randombytes: 2.1.0 + dev: false + + /browserify-sign@4.2.3: + resolution: {integrity: sha512-JWCZW6SKhfhjJxO8Tyiiy+XYB7cqd2S5/+WeYHsKdNKFlCBhKbblba1A/HN/90YwtxKc8tCErjffZl++UNmGiw==} + engines: {node: '>= 0.12'} + dependencies: + bn.js: 5.2.1 + browserify-rsa: 4.1.0 + create-hash: 1.2.0 + create-hmac: 1.1.7 + elliptic: 6.5.5 + hash-base: 3.0.4 + inherits: 2.0.4 + parse-asn1: 5.1.7 + readable-stream: 2.3.8 + safe-buffer: 5.2.1 + dev: false + + /browserify-zlib@0.2.0: + resolution: {integrity: sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA==} + dependencies: + pako: 1.0.11 + dev: false + /bs58@4.0.1: resolution: {integrity: sha512-Ok3Wdf5vOIlBrgCvTq96gBkJw+JUEzdBgyaza5HLtPm7yTHkjRy8+JzNyHF7BHa0bNWOQIp3m5YF0nnFcOIKLw==} dependencies: @@ -1530,6 +2626,25 @@ packages: base-x: 4.0.0 dev: false + /buffer-alloc-unsafe@1.1.0: + resolution: {integrity: sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg==} + dev: false + + /buffer-alloc@1.2.0: + resolution: {integrity: sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow==} + dependencies: + buffer-alloc-unsafe: 1.1.0 + buffer-fill: 1.0.0 + dev: false + + /buffer-fill@1.0.0: + resolution: {integrity: sha512-T7zexNBwiiaCOGDg9xNX9PBmjrubblRkENuptryuI64URkXDFum9il/JGL8Lm8wYfAXpredVXXZz7eMHilimiQ==} + dev: false + + /buffer-from@1.1.2: + resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} + dev: false + /buffer-layout@1.2.2: resolution: {integrity: sha512-kWSuLN694+KTk8SrYvCqwP2WcgQjoRCiF5b4QDvkkz8EmgD+aWAIceGFKMIAdmF/pH+vpgNV3d3kAKorcdAmWA==} engines: {node: '>=4.5'} @@ -1539,6 +2654,10 @@ packages: resolution: {integrity: sha512-M87YIUBsZ6N924W57vDwT/aOu8hw7ZgdByz6ijksLjmHJELBASmYTTlNHRgjE+pTsT9oJXGaDSgqqwfdHotDUg==} dev: false + /buffer-xor@1.0.3: + resolution: {integrity: sha512-571s0T7nZWK6vB67HI5dyUF7wXiNcfaPPPTl6zYCNApANjIvYJTg7hlud/+cJpdAhS7dVzqMLmfhfHR3rAcOjQ==} + dev: false + /buffer@5.7.1: resolution: {integrity: sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==} dependencies: @@ -1561,6 +2680,10 @@ packages: node-gyp-build: 4.8.1 dev: false + /builtin-status-codes@3.0.0: + resolution: {integrity: sha512-HpGFw18DgFWlncDfjTa2rcQ4W88O1mC8e8yZ2AvQY5KDaktSTwo+KRf6nHK6FRI5FyRyb/5T6+TSxfP7QyGsmQ==} + dev: false + /call-bind@1.0.7: resolution: {integrity: sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==} engines: {node: '>= 0.4'} @@ -1572,6 +2695,11 @@ packages: set-function-length: 1.2.2 dev: false + /camelcase@5.3.1: + resolution: {integrity: sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==} + engines: {node: '>=6'} + dev: false + /chalk@4.1.2: resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} engines: {node: '>=10'} @@ -1589,6 +2717,21 @@ packages: resolution: {integrity: sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==} dev: false + /chokidar@3.6.0: + resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==} + engines: {node: '>= 8.10.0'} + dependencies: + anymatch: 3.1.3 + braces: 3.0.3 + glob-parent: 5.1.2 + is-binary-path: 2.1.0 + is-glob: 4.0.3 + normalize-path: 3.0.0 + readdirp: 3.6.0 + optionalDependencies: + fsevents: 2.3.3 + dev: false + /cipher-base@1.0.4: resolution: {integrity: sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==} dependencies: @@ -1596,6 +2739,12 @@ packages: safe-buffer: 5.2.1 dev: false + /citty@0.1.6: + resolution: {integrity: sha512-tskPPKEs8D2KPafUypv2gxwJP8h/OaJmC82QQGGDQcHvXX43xF2VDACcJVmZ0EuSxkpO9Kc4MlrA3q0+FG58AQ==} + dependencies: + consola: 3.2.3 + dev: false + /cli-cursor@3.1.0: resolution: {integrity: sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==} engines: {node: '>=8'} @@ -1613,11 +2762,34 @@ packages: engines: {node: '>= 10'} dev: false + /clipboardy@4.0.0: + resolution: {integrity: sha512-5mOlNS0mhX0707P2I0aZ2V/cmHUEO/fL7VFLqszkhUsxt7RwnmrInf/eEQKlf5GzvYeHIjT+Ov1HRfNmymlG0w==} + engines: {node: '>=18'} + dependencies: + execa: 8.0.1 + is-wsl: 3.1.0 + is64bit: 2.0.0 + dev: false + + /cliui@5.0.0: + resolution: {integrity: sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==} + dependencies: + string-width: 3.1.0 + strip-ansi: 5.2.0 + wrap-ansi: 5.1.0 + dev: false + /clone@1.0.4: resolution: {integrity: sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==} engines: {node: '>=0.8'} dev: false + /color-convert@1.9.3: + resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==} + dependencies: + color-name: 1.1.3 + dev: false + /color-convert@2.0.1: resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} engines: {node: '>=7.0.0'} @@ -1625,6 +2797,10 @@ packages: color-name: 1.1.4 dev: false + /color-name@1.1.3: + resolution: {integrity: sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==} + dev: false + /color-name@1.1.4: resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} dev: false @@ -1650,13 +2826,51 @@ packages: engines: {node: '>= 12'} dev: false - /create-hash@1.2.0: - resolution: {integrity: sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==} - dependencies: - cipher-base: 1.0.4 - inherits: 2.0.4 - md5.js: 1.3.5 - ripemd160: 2.0.2 + /confbox@0.1.7: + resolution: {integrity: sha512-uJcB/FKZtBMCJpK8MQji6bJHgu1tixKPxRLeGkNzBoOZzpnZUJm0jm2/sBDWcuBx1dYgxV4JU+g5hmNxCyAmdA==} + dev: false + + /consola@3.2.3: + resolution: {integrity: sha512-I5qxpzLv+sJhTVEoLYNcTW+bThDCPsit0vLNKShZx6rLtpilNpmmeTPaeqJb9ZE9dV3DGaeby6Vuhrw38WjeyQ==} + engines: {node: ^14.18.0 || >=16.10.0} + dev: false + + /console-browserify@1.2.0: + resolution: {integrity: sha512-ZMkYO/LkF17QvCPqM0gxw8yUzigAOZOSWSHg91FH6orS7vcEj5dVZTidN2fQ14yBSdg97RqhSNwLUXInd52OTA==} + dev: false + + /constants-browserify@1.0.0: + resolution: {integrity: sha512-xFxOwqIzR/e1k1gLiWEophSCMqXcwVHIH7akf7b/vxcUeGunlj3hvZaaqxwHsTgn+IndtkQJgSztIDWeumWJDQ==} + dev: false + + /cookie-es@1.1.0: + resolution: {integrity: sha512-L2rLOcK0wzWSfSDA33YR+PUHDG10a8px7rUHKWbGLP4YfbsMed2KFUw5fczvDPbT98DDe3LEzviswl810apTEw==} + dev: false + + /copy-to-clipboard@3.3.3: + resolution: {integrity: sha512-2KV8NhB5JqC3ky0r9PMCAZKbUHSwtEo4CwCs0KXgruG43gX5PMqDEBbVU4OUzw2MuAWUfsuFmWvEKG5QRfSnJA==} + dependencies: + toggle-selection: 1.0.6 + dev: false + + /core-util-is@1.0.3: + resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==} + dev: false + + /create-ecdh@4.0.4: + resolution: {integrity: sha512-mf+TCx8wWc9VpuxfP2ht0iSISLZnt0JgWlrOKZiNqyUZWnjIaCIVNQArMHnCZKfEYRg6IM7A+NeJoN8gf/Ws0A==} + dependencies: + bn.js: 4.12.0 + elliptic: 6.5.5 + dev: false + + /create-hash@1.2.0: + resolution: {integrity: sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==} + dependencies: + cipher-base: 1.0.4 + inherits: 2.0.4 + md5.js: 1.3.5 + ripemd160: 2.0.2 sha.js: 2.4.11 dev: false @@ -1671,6 +2885,10 @@ packages: sha.js: 2.4.11 dev: false + /create-require@1.1.1: + resolution: {integrity: sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==} + dev: false + /cross-fetch@3.1.8: resolution: {integrity: sha512-cvA+JwZoU0Xq+h6WkMvAUqPEYy92Obet6UdKLfW60qn99ftItKjB5T+BkyWOFWe2pUyfQ+IJHmpOTznqk1M6Kg==} dependencies: @@ -1679,6 +2897,40 @@ packages: - encoding dev: false + /cross-spawn@7.0.3: + resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} + engines: {node: '>= 8'} + dependencies: + path-key: 3.1.1 + shebang-command: 2.0.0 + which: 2.0.2 + dev: false + + /crossws@0.2.4: + resolution: {integrity: sha512-DAxroI2uSOgUKLz00NX6A8U/8EE3SZHmIND+10jkVSaypvyt57J5JEOxAQOL6lQxyzi/wZbTIwssU1uy69h5Vg==} + peerDependencies: + uWebSockets.js: '*' + peerDependenciesMeta: + uWebSockets.js: + optional: true + dev: false + + /crypto-browserify@3.12.0: + resolution: {integrity: sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg==} + dependencies: + browserify-cipher: 1.0.1 + browserify-sign: 4.2.3 + create-ecdh: 4.0.4 + create-hash: 1.2.0 + create-hmac: 1.1.7 + diffie-hellman: 5.0.3 + inherits: 2.0.4 + pbkdf2: 3.1.2 + public-encrypt: 4.0.3 + randombytes: 2.1.0 + randomfill: 1.0.4 + dev: false + /crypto-js@4.2.0: resolution: {integrity: sha512-KALDyEYgpY+Rlob/iriUtjV6d5Eq+Y191A5g4UqLAi8CyGP9N1+FdVbkc1SxKc2r4YAYqG8JzO2KGL+AizD70Q==} dev: false @@ -1717,6 +2969,16 @@ packages: ms: 2.1.2 dev: false + /decamelize@1.2.0: + resolution: {integrity: sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==} + engines: {node: '>=0.10.0'} + dev: false + + /decode-uri-component@0.2.2: + resolution: {integrity: sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ==} + engines: {node: '>=0.10'} + dev: false + /defaults@1.0.4: resolution: {integrity: sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==} dependencies: @@ -1732,6 +2994,19 @@ packages: gopd: 1.0.1 dev: false + /define-properties@1.2.1: + resolution: {integrity: sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==} + engines: {node: '>= 0.4'} + dependencies: + define-data-property: 1.1.4 + has-property-descriptors: 1.0.2 + object-keys: 1.1.1 + dev: false + + /defu@6.1.4: + resolution: {integrity: sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg==} + dev: false + /delay@5.0.0: resolution: {integrity: sha512-ReEBKkIfe4ya47wlPYf/gu5ib6yUG0/Aez0JQZQz94kiWtRQvZIQbTiehsnwHvLSWJnQdhVeqYue7Id1dKr0qw==} engines: {node: '>=10'} @@ -1752,11 +3027,62 @@ packages: engines: {node: '>= 0.8'} dev: false + /des.js@1.1.0: + resolution: {integrity: sha512-r17GxjhUCjSRy8aiJpr8/UadFIzMzJGexI3Nmz4ADi9LYSFx4gTBp80+NaX/YsXWWLhpZ7v/v/ubEc/bCNfKwg==} + dependencies: + inherits: 2.0.4 + minimalistic-assert: 1.0.1 + dev: false + + /destr@2.0.3: + resolution: {integrity: sha512-2N3BOUU4gYMpTP24s5rF5iP7BDr7uNTCs4ozw3kf/eKfvWSIu93GEBi5m427YoyJoeOzQ5smuu4nNAPGb8idSQ==} + dev: false + + /detect-browser@5.2.0: + resolution: {integrity: sha512-tr7XntDAu50BVENgQfajMLzacmSe34D+qZc4zjnniz0ZVuw/TZcLcyxHQjYpJTM36sGEkZZlYLnIM1hH7alTMA==} + dev: false + + /detect-browser@5.3.0: + resolution: {integrity: sha512-53rsFbGdwMwlF7qvCt0ypLM5V5/Mbl0szB7GPN8y9NCcbknYOeVVXdrXEq+90IwAfrrzt6Hd+u2E2ntakICU8w==} + dev: false + + /detect-libc@1.0.3: + resolution: {integrity: sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg==} + engines: {node: '>=0.10'} + hasBin: true + dev: false + + /diffie-hellman@5.0.3: + resolution: {integrity: sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==} + dependencies: + bn.js: 4.12.0 + miller-rabin: 4.0.1 + randombytes: 2.1.0 + dev: false + + /dijkstrajs@1.0.3: + resolution: {integrity: sha512-qiSlmBq9+BCdCA/L46dw8Uy93mloxsPSbwnm5yrKn2vMPiy8KyAskTF6zuV/j5BMsmOGZDPs7KjU+mjb670kfA==} + dev: false + + /domain-browser@4.23.0: + resolution: {integrity: sha512-ArzcM/II1wCCujdCNyQjXrAFwS4mrLh4C7DZWlaI8mdh7h3BfKdNd3bKXITfl2PT9FtfQqaGvhi1vPRQPimjGA==} + engines: {node: '>=10'} + dev: false + /dotenv@10.0.0: resolution: {integrity: sha512-rlBi9d8jpv9Sf1klPjNfFAuWDjKLwTIJJ/VxtoTwIR6hnZxcEOQCZg2oIL3MWBYw5GpUDKOEnND7LXTbIpQ03Q==} engines: {node: '>=10'} dev: false + /duplexify@4.1.3: + resolution: {integrity: sha512-M3BmBhwJRZsSx38lZyhE53Csddgzl5R7xGJNk7CVddZD6CcmwMCH8J+7AprIrQKH7TonKxaCjcv27Qmf+sQ+oA==} + dependencies: + end-of-stream: 1.4.4 + inherits: 2.0.4 + readable-stream: 3.6.2 + stream-shift: 1.0.3 + dev: false + /elliptic@6.5.4: resolution: {integrity: sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ==} dependencies: @@ -1781,10 +3107,20 @@ packages: minimalistic-crypto-utils: 1.0.1 dev: false + /emoji-regex@7.0.3: + resolution: {integrity: sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==} + dev: false + /emoji-regex@8.0.0: resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} dev: false + /end-of-stream@1.4.4: + resolution: {integrity: sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==} + dependencies: + once: 1.4.0 + dev: false + /es-define-property@1.0.0: resolution: {integrity: sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==} engines: {node: '>= 0.4'} @@ -1807,11 +3143,46 @@ packages: es6-promise: 4.2.8 dev: false + /esbuild@0.20.2: + resolution: {integrity: sha512-WdOOppmUNU+IbZ0PaDiTst80zjnrOkyJNHoKupIcVyU8Lvla3Ugx94VzkQ32Ijqd7UhHJy75gNWDMUekcrSJ6g==} + engines: {node: '>=12'} + hasBin: true + requiresBuild: true + optionalDependencies: + '@esbuild/aix-ppc64': 0.20.2 + '@esbuild/android-arm': 0.20.2 + '@esbuild/android-arm64': 0.20.2 + '@esbuild/android-x64': 0.20.2 + '@esbuild/darwin-arm64': 0.20.2 + '@esbuild/darwin-x64': 0.20.2 + '@esbuild/freebsd-arm64': 0.20.2 + '@esbuild/freebsd-x64': 0.20.2 + '@esbuild/linux-arm': 0.20.2 + '@esbuild/linux-arm64': 0.20.2 + '@esbuild/linux-ia32': 0.20.2 + '@esbuild/linux-loong64': 0.20.2 + '@esbuild/linux-mips64el': 0.20.2 + '@esbuild/linux-ppc64': 0.20.2 + '@esbuild/linux-riscv64': 0.20.2 + '@esbuild/linux-s390x': 0.20.2 + '@esbuild/linux-x64': 0.20.2 + '@esbuild/netbsd-x64': 0.20.2 + '@esbuild/openbsd-x64': 0.20.2 + '@esbuild/sunos-x64': 0.20.2 + '@esbuild/win32-arm64': 0.20.2 + '@esbuild/win32-ia32': 0.20.2 + '@esbuild/win32-x64': 0.20.2 + dev: false + /escape-string-regexp@1.0.5: resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==} engines: {node: '>=0.8.0'} dev: false + /estree-walker@2.0.2: + resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==} + dev: false + /ethereum-bloom-filters@1.1.0: resolution: {integrity: sha512-J1gDRkLpuGNvWYzWslBQR9cDV4nd4kfvVTE/Wy4Kkm4yb3EYRSlyi0eB/inTsSTTVyA0+HyzHgbr95Fn/Z1fSw==} dependencies: @@ -1843,6 +3214,33 @@ packages: resolution: {integrity: sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==} dev: false + /events@3.3.0: + resolution: {integrity: sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==} + engines: {node: '>=0.8.x'} + dev: false + + /evp_bytestokey@1.0.3: + resolution: {integrity: sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==} + dependencies: + md5.js: 1.3.5 + safe-buffer: 5.2.1 + dev: false + + /execa@8.0.1: + resolution: {integrity: sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==} + engines: {node: '>=16.17'} + dependencies: + cross-spawn: 7.0.3 + get-stream: 8.0.1 + human-signals: 5.0.0 + is-stream: 3.0.0 + merge-stream: 2.0.0 + npm-run-path: 5.3.0 + onetime: 6.0.0 + signal-exit: 4.1.0 + strip-final-newline: 3.0.0 + dev: false + /exponential-backoff@3.1.1: resolution: {integrity: sha512-dX7e/LHVJ6W3DE1MHWi9S1EYzDESENfLrYohG2G++ovZrYOkm4Knwa0mc1cn84xJOR4KEU0WSchhLbd0UklbHw==} requiresBuild: true @@ -1863,6 +3261,11 @@ packages: engines: {node: '> 0.1.90'} dev: false + /fast-redact@3.5.0: + resolution: {integrity: sha512-dwsoQlS7h9hMeYUq1W++23NDcBLV4KqONnITDV9DjfS3q1SgDGVrBdvvTLUotWtPSD7asWDV9/CmsZPy8Hf70A==} + engines: {node: '>=6'} + dev: false + /fast-stable-stringify@1.0.0: resolution: {integrity: sha512-wpYMUmFu5f00Sm0cj2pfivpmawLZ0NKdviQ4w9zJeR8JVtOpOxHmLaJuj0vxvGqMJQWyP/COUkF75/57OKyRag==} dev: false @@ -1882,6 +3285,33 @@ packages: resolution: {integrity: sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==} dev: false + /fill-range@7.1.1: + resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} + engines: {node: '>=8'} + dependencies: + to-regex-range: 5.0.1 + dev: false + + /filter-obj@1.1.0: + resolution: {integrity: sha512-8rXg1ZnX7xzy2NGDVkBVaAy+lSlPNwad13BtgSlLuxfIslyt5Vg64U7tFcCt4WS1R0hvtnQybT/IyCkGZ3DpXQ==} + engines: {node: '>=0.10.0'} + dev: false + + /find-up@3.0.0: + resolution: {integrity: sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==} + engines: {node: '>=6'} + dependencies: + locate-path: 3.0.0 + dev: false + + /find-up@5.0.0: + resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} + engines: {node: '>=10'} + dependencies: + locate-path: 6.0.0 + path-exists: 4.0.0 + dev: false + /follow-redirects@1.15.6(debug@4.3.4): resolution: {integrity: sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==} engines: {node: '>=4.0'} @@ -1909,10 +3339,23 @@ packages: mime-types: 2.1.35 dev: false + /fsevents@2.3.3: + resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} + engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} + os: [darwin] + requiresBuild: true + dev: false + optional: true + /function-bind@1.1.2: resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} dev: false + /get-caller-file@2.0.5: + resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} + engines: {node: 6.* || 8.* || >= 10.*} + dev: false + /get-intrinsic@1.2.4: resolution: {integrity: sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==} engines: {node: '>= 0.4'} @@ -1924,12 +3367,45 @@ packages: hasown: 2.0.2 dev: false + /get-port-please@3.1.2: + resolution: {integrity: sha512-Gxc29eLs1fbn6LQ4jSU4vXjlwyZhF5HsGuMAa7gqBP4Rw4yxxltyDUuF5MBclFzDTXO+ACchGQoeela4DSfzdQ==} + dev: false + + /get-stream@8.0.1: + resolution: {integrity: sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==} + engines: {node: '>=16'} + dev: false + + /glob-parent@5.1.2: + resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} + engines: {node: '>= 6'} + dependencies: + is-glob: 4.0.3 + dev: false + /gopd@1.0.1: resolution: {integrity: sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==} dependencies: get-intrinsic: 1.2.4 dev: false + /h3@1.11.1: + resolution: {integrity: sha512-AbaH6IDnZN6nmbnJOH72y3c5Wwh9P97soSVdGSBbcDACRdkC0FEWf25pzx4f/NuOCK6quHmW18yF2Wx+G4Zi1A==} + dependencies: + cookie-es: 1.1.0 + crossws: 0.2.4 + defu: 6.1.4 + destr: 2.0.3 + iron-webcrypto: 1.2.1 + ohash: 1.1.3 + radix3: 1.1.2 + ufo: 1.5.3 + uncrypto: 0.1.3 + unenv: 1.9.0 + transitivePeerDependencies: + - uWebSockets.js + dev: false + /has-flag@4.0.0: resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} engines: {node: '>=8'} @@ -1958,6 +3434,14 @@ packages: has-symbols: 1.0.3 dev: false + /hash-base@3.0.4: + resolution: {integrity: sha512-EeeoJKjTyt868liAlVmcv2ZsUfGHlE3Q+BICOXcZiwN3osr5Q/zFGYmTJpoIzuaSTAwndFy+GqhEwlU4L3j4Ow==} + engines: {node: '>=4'} + dependencies: + inherits: 2.0.4 + safe-buffer: 5.2.1 + dev: false + /hash-base@3.1.0: resolution: {integrity: sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA==} engines: {node: '>=4'} @@ -2004,6 +3488,20 @@ packages: toidentifier: 1.0.1 dev: false + /http-shutdown@1.2.2: + resolution: {integrity: sha512-S9wWkJ/VSY9/k4qcjG318bqJNruzE4HySUhFYknwmu6LBP97KLLfwNf+n4V1BHurvFNkSKLFnK/RsuUnRTf9Vw==} + engines: {iojs: '>= 1.0.0', node: '>= 0.12.0'} + dev: false + + /https-browserify@1.0.0: + resolution: {integrity: sha512-J+FkSdyD+0mA0N+81tMotaRMfSL9SGi+xpD3T6YApKsc3bGSXJlfXri3VyFOeYkfLRQisDk1W+jIFFKBeUBbBg==} + dev: false + + /human-signals@5.0.0: + resolution: {integrity: sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==} + engines: {node: '>=16.17.0'} + dev: false + /humanize-ms@1.2.1: resolution: {integrity: sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==} dependencies: @@ -2017,6 +3515,10 @@ packages: safer-buffer: 2.1.2 dev: false + /idb-keyval@6.2.1: + resolution: {integrity: sha512-8Sb3veuYCyrZL+VBt9LJfZjLUPWVvqn8tG28VqYNFCo43KHcKuq+b4EiXGeuaLAQWL2YmyDgMp2aSpH9JHsEQg==} + dev: false + /ieee754@1.2.1: resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} dev: false @@ -2046,6 +3548,10 @@ packages: wrap-ansi: 6.2.0 dev: false + /iron-webcrypto@1.2.1: + resolution: {integrity: sha512-feOM6FaSr6rEABp/eDfVseKyTMDt+KGpeB35SkVn9Tyn0CqvVsY3EwI0v5i8nMHyJnzCIQf7nsy3p41TPkJZhg==} + dev: false + /is-arguments@1.1.1: resolution: {integrity: sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==} engines: {node: '>= 0.4'} @@ -2054,11 +3560,40 @@ packages: has-tostringtag: 1.0.2 dev: false + /is-binary-path@2.1.0: + resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==} + engines: {node: '>=8'} + dependencies: + binary-extensions: 2.3.0 + dev: false + /is-callable@1.2.7: resolution: {integrity: sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==} engines: {node: '>= 0.4'} dev: false + /is-core-module@2.13.1: + resolution: {integrity: sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==} + dependencies: + hasown: 2.0.2 + dev: false + + /is-docker@3.0.0: + resolution: {integrity: sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + hasBin: true + dev: false + + /is-extglob@2.1.1: + resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} + engines: {node: '>=0.10.0'} + dev: false + + /is-fullwidth-code-point@2.0.0: + resolution: {integrity: sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w==} + engines: {node: '>=4'} + dev: false + /is-fullwidth-code-point@3.0.0: resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} engines: {node: '>=8'} @@ -2071,16 +3606,49 @@ packages: has-tostringtag: 1.0.2 dev: false + /is-glob@4.0.3: + resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} + engines: {node: '>=0.10.0'} + dependencies: + is-extglob: 2.1.1 + dev: false + /is-hex-prefixed@1.0.0: resolution: {integrity: sha512-WvtOiug1VFrE9v1Cydwm+FnXd3+w9GaeVUss5W4v/SLy3UW00vP+6iNF2SdnfiBoLy4bTqVdkftNGTUeOFVsbA==} engines: {node: '>=6.5.0', npm: '>=3'} dev: false + /is-inside-container@1.0.0: + resolution: {integrity: sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==} + engines: {node: '>=14.16'} + hasBin: true + dependencies: + is-docker: 3.0.0 + dev: false + /is-interactive@1.0.0: resolution: {integrity: sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==} engines: {node: '>=8'} dev: false + /is-nan@1.3.2: + resolution: {integrity: sha512-E+zBKpQ2t6MEo1VsonYmluk9NxGrbzpeeLC2xIViuO2EjU2xsXsBPwTr3Ykv9l08UYEVEdWeRZNouaZqF6RN0w==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.7 + define-properties: 1.2.1 + dev: false + + /is-number@7.0.0: + resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} + engines: {node: '>=0.12.0'} + dev: false + + /is-stream@3.0.0: + resolution: {integrity: sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + dev: false + /is-typed-array@1.1.13: resolution: {integrity: sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw==} engines: {node: '>= 0.4'} @@ -2093,6 +3661,46 @@ packages: engines: {node: '>=10'} dev: false + /is-wsl@3.1.0: + resolution: {integrity: sha512-UcVfVfaK4Sc4m7X3dUSoHoozQGBEFeDC+zVo06t98xe8CzHSZZBekNXH+tu0NalHolcJ/QAGqS46Hef7QXBIMw==} + engines: {node: '>=16'} + dependencies: + is-inside-container: 1.0.0 + dev: false + + /is64bit@2.0.0: + resolution: {integrity: sha512-jv+8jaWCl0g2lSBkNSVXdzfBA0npK1HGC2KtWM9FumFRoGS94g3NbCCLVnCYHLjp4GrW2KZeeSTMo5ddtznmGw==} + engines: {node: '>=18'} + dependencies: + system-architecture: 0.1.0 + dev: false + + /isarray@1.0.0: + resolution: {integrity: sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==} + dev: false + + /isarray@2.0.5: + resolution: {integrity: sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==} + dev: false + + /isexe@2.0.0: + resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} + dev: false + + /isomorphic-timers-promises@1.0.1: + resolution: {integrity: sha512-u4sej9B1LPSxTGKB/HiuzvEQnXH0ECYkSVQU39koSwmFAxhlEAFl9RdTvLv4TOTQUgBS5O3O5fwUxk6byBZ+IQ==} + engines: {node: '>=10'} + dev: false + + /isomorphic-unfetch@3.1.0: + resolution: {integrity: sha512-geDJjpoZ8N0kWexiwkX8F9NkTsXhetLPVbZFQ+JTW239QNOwvB0gniuR1Wc6f0AMTn7/mFGyXvHTifrCp/GH8Q==} + dependencies: + node-fetch: 2.7.0 + unfetch: 4.2.0 + transitivePeerDependencies: + - encoding + dev: false + /isomorphic-ws@4.0.1(ws@7.5.9): resolution: {integrity: sha512-BhBvN2MBpWTaSHdWRb/bwdZJ1WaehQ2L1KngkCkfLUGF0mAWAT1sQUQacEmQ0jXkFw/czDXPNQSL5u2/Krsz1w==} peerDependencies: @@ -2123,6 +3731,11 @@ packages: - utf-8-validate dev: false + /jiti@1.21.0: + resolution: {integrity: sha512-gFqAIbuKyyso/3G2qhiO2OM6shY6EPP/R0+mkDbyspxKazh8BXDC5FiFsUjlczgdNz/vfra0da2y+aHrusLG/Q==} + hasBin: true + dev: false + /js-sha256@0.9.0: resolution: {integrity: sha512-sga3MHh9sgQN2+pJ9VYZ+1LPwXOxuBJBA5nrR5/ofPfuiJBE2hnjsaN8se8JznOmGLN2p49Pe5U/ttafcs/apA==} dev: false @@ -2160,6 +3773,51 @@ packages: readable-stream: 3.6.2 dev: false + /keyvaluestorage-interface@1.0.0: + resolution: {integrity: sha512-8t6Q3TclQ4uZynJY9IGr2+SsIGwK9JHcO6ootkHCGA0CrQCRy+VkouYNO2xicET6b9al7QKzpebNow+gkpCL8g==} + dev: false + + /listhen@1.7.2: + resolution: {integrity: sha512-7/HamOm5YD9Wb7CFgAZkKgVPA96WwhcTQoqtm2VTZGVbVVn3IWKRBTgrU7cchA3Q8k9iCsG8Osoi9GX4JsGM9g==} + hasBin: true + dependencies: + '@parcel/watcher': 2.4.1 + '@parcel/watcher-wasm': 2.4.1 + citty: 0.1.6 + clipboardy: 4.0.0 + consola: 3.2.3 + crossws: 0.2.4 + defu: 6.1.4 + get-port-please: 3.1.2 + h3: 1.11.1 + http-shutdown: 1.2.2 + jiti: 1.21.0 + mlly: 1.7.0 + node-forge: 1.3.1 + pathe: 1.1.2 + std-env: 3.7.0 + ufo: 1.5.3 + untun: 0.1.3 + uqr: 0.1.2 + transitivePeerDependencies: + - uWebSockets.js + dev: false + + /locate-path@3.0.0: + resolution: {integrity: sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==} + engines: {node: '>=6'} + dependencies: + p-locate: 3.0.0 + path-exists: 3.0.0 + dev: false + + /locate-path@6.0.0: + resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} + engines: {node: '>=10'} + dependencies: + p-locate: 5.0.0 + dev: false + /lodash.clonedeep@4.5.0: resolution: {integrity: sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ==} dev: false @@ -2180,6 +3838,17 @@ packages: is-unicode-supported: 0.1.0 dev: false + /lru-cache@10.2.2: + resolution: {integrity: sha512-9hp3Vp2/hFQUiIwKo8XCeFVnrg8Pk3TYNPIR7tJADKi5YfcF7vEaK7avFHTlSy3kOKYaJQaalfEo6YuXdceBOQ==} + engines: {node: 14 || >=16.14} + dev: false + + /magic-string@0.30.10: + resolution: {integrity: sha512-iIRwTIf0QKV3UAnYK4PU8uiEc4SRh5jX0mwpIwETPpHdhVM4f53RSwS/vXvN1JhGX+Cs7B8qIq3d6AH49O5fAQ==} + dependencies: + '@jridgewell/sourcemap-codec': 1.4.15 + dev: false + /md5.js@1.3.5: resolution: {integrity: sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==} dependencies: @@ -2188,6 +3857,10 @@ packages: safe-buffer: 5.2.1 dev: false + /merge-stream@2.0.0: + resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} + dev: false + /merkletreejs@0.3.11: resolution: {integrity: sha512-LJKTl4iVNTndhL+3Uz/tfkjD0klIWsHlUzgtuNnNrsf7bAlXR30m+xYB7lHr5Z/l6e/yAIsr26Dabx6Buo4VGQ==} engines: {node: '>= 7.6.0'} @@ -2203,6 +3876,22 @@ packages: resolution: {integrity: sha512-/0LLxhzP0tfiR5hcQebtudP56gUurs2CLkGarnCiB/OqEyUFQ6U3paQi/tgLv0hBJYt2rnr9MNpxz4fiiugstg==} dev: false + /micromatch@4.0.6: + resolution: {integrity: sha512-Y4Ypn3oujJYxJcMacVgcs92wofTHxp9FzfDpQON4msDefoC0lb3ETvQLOdLcbhSwU1bz8HrL/1sygfBIHudrkQ==} + engines: {node: '>=8.6'} + dependencies: + braces: 3.0.3 + picomatch: 4.0.2 + dev: false + + /miller-rabin@4.0.1: + resolution: {integrity: sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==} + hasBin: true + dependencies: + bn.js: 4.12.0 + brorand: 1.1.0 + dev: false + /mime-db@1.52.0: resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} engines: {node: '>= 0.6'} @@ -2226,7 +3915,12 @@ packages: engines: {node: '>=6'} dev: false - /minimalistic-assert@1.0.1: + /mimic-fn@4.0.0: + resolution: {integrity: sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==} + engines: {node: '>=12'} + dev: false + + /minimalistic-assert@1.0.1: resolution: {integrity: sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==} dev: false @@ -2239,6 +3933,20 @@ packages: engines: {node: '>= 8.0.0'} dev: false + /mlly@1.7.0: + resolution: {integrity: sha512-U9SDaXGEREBYQgfejV97coK0UL1r+qnF2SyO9A3qcI8MzKnsIFKHNVEkrDyNncQTKQQumsasmeq84eNMdBfsNQ==} + dependencies: + acorn: 8.11.3 + pathe: 1.1.2 + pkg-types: 1.1.1 + ufo: 1.5.3 + dev: false + + /mri@1.2.0: + resolution: {integrity: sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==} + engines: {node: '>=4'} + dev: false + /ms@2.1.2: resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==} dev: false @@ -2247,6 +3955,10 @@ packages: resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} dev: false + /multiformats@9.9.0: + resolution: {integrity: sha512-HoMUjhH9T8DDBNT+6xzkrd9ga/XiBI4xLr58LJACwK6G3HTOPeMz4nB4KJs33L2BelrIJa7P0VuNaVF3hMYfjg==} + dev: false + /multistream@4.1.0: resolution: {integrity: sha512-J1XDiAmmNpRCBfIWJv+n0ymC4ABcf/Pl+5YvC5B/D2f/2+8PtHvCNxMPKiQcZyi922Hq69J2YOpb1pTywfifyw==} requiresBuild: true @@ -2265,6 +3977,12 @@ packages: resolution: {integrity: sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==} dev: false + /nanoid@3.3.7: + resolution: {integrity: sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==} + engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} + hasBin: true + dev: false + /near-hd-key@1.2.1: resolution: {integrity: sha512-SIrthcL5Wc0sps+2e1xGj3zceEa68TgNZDLuCx0daxmfTP7sFTB3/mtE2pYhlFsCxWoMn+JfID5E1NlzvvbRJg==} dependencies: @@ -2290,6 +4008,15 @@ packages: resolution: {integrity: sha512-eh0GgfEkpnoWDq+VY8OyvYhFEzBk6jIYbRKdIlyTiAXIVJ8PyBaKb0rp7oDtoddbdoHWhq8wwr+XZ81F1rpNdA==} dev: false + /node-addon-api@7.1.0: + resolution: {integrity: sha512-mNcltoe1R8o7STTegSOHdnJNN7s5EUvhoS7ShnTHDyOSd+8H+UdWODq6qSv67PjC8Zc5JRT8+oLAMCr0SIXw7g==} + engines: {node: ^16 || ^18 || >= 20} + dev: false + + /node-fetch-native@1.6.4: + resolution: {integrity: sha512-IhOigYzAKHd244OC0JIMIUrjzctirCmPkaIfhDeGcEETWof5zKYUW7e7MYvChGWh/4CJeXEgsRyGzuF334rOOQ==} + dev: false + /node-fetch@2.7.0: resolution: {integrity: sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==} engines: {node: 4.x || >=6.0.0} @@ -2302,12 +4029,62 @@ packages: whatwg-url: 5.0.0 dev: false + /node-forge@1.3.1: + resolution: {integrity: sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==} + engines: {node: '>= 6.13.0'} + dev: false + /node-gyp-build@4.8.1: resolution: {integrity: sha512-OSs33Z9yWr148JZcbZd5WiAXhh/n9z8TxQcdMhIOlpN9AhWpLfvVFO73+m77bBABQMaY9XSvIa+qk0jlI7Gcaw==} hasBin: true requiresBuild: true dev: false + /node-stdlib-browser@1.2.0: + resolution: {integrity: sha512-VSjFxUhRhkyed8AtLwSCkMrJRfQ3e2lGtG3sP6FEgaLKBBbxM/dLfjRe1+iLhjvyLFW3tBQ8+c0pcOtXGbAZJg==} + engines: {node: '>=10'} + dependencies: + assert: 2.1.0 + browser-resolve: 2.0.0 + browserify-zlib: 0.2.0 + buffer: 5.7.1 + console-browserify: 1.2.0 + constants-browserify: 1.0.0 + create-require: 1.1.1 + crypto-browserify: 3.12.0 + domain-browser: 4.23.0 + events: 3.3.0 + https-browserify: 1.0.0 + isomorphic-timers-promises: 1.0.1 + os-browserify: 0.3.0 + path-browserify: 1.0.1 + pkg-dir: 5.0.0 + process: 0.11.10 + punycode: 1.4.1 + querystring-es3: 0.2.1 + readable-stream: 3.6.2 + stream-browserify: 3.0.0 + stream-http: 3.2.0 + string_decoder: 1.3.0 + timers-browserify: 2.0.12 + tty-browserify: 0.0.1 + url: 0.11.3 + util: 0.12.5 + vm-browserify: 1.1.2 + dev: false + + /normalize-path@3.0.0: + resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} + engines: {node: '>=0.10.0'} + dev: false + + /npm-run-path@5.3.0: + resolution: {integrity: sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + dependencies: + path-key: 4.0.0 + dev: false + /number-to-bn@1.7.0: resolution: {integrity: sha512-wsJ9gfSz1/s4ZsJN01lyonwuxA1tml6X1yBDnfpMglypcBRFZZkus26EdPSlqS5GJfYddVZa22p3VNb3z5m5Ig==} engines: {node: '>=6.5.0', npm: '>=3'} @@ -2316,13 +4093,55 @@ packages: strip-hex-prefix: 1.0.0 dev: false + /object-inspect@1.13.1: + resolution: {integrity: sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==} + dev: false + + /object-is@1.1.6: + resolution: {integrity: sha512-F8cZ+KfGlSGi09lJT7/Nd6KJZ9ygtvYC0/UYYLI9nmQKLMnydpB9yvbv9K1uSkEu7FU9vYPmVwLg328tX+ot3Q==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.7 + define-properties: 1.2.1 + dev: false + + /object-keys@1.1.1: + resolution: {integrity: sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==} + engines: {node: '>= 0.4'} + dev: false + + /object.assign@4.1.5: + resolution: {integrity: sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.7 + define-properties: 1.2.1 + has-symbols: 1.0.3 + object-keys: 1.1.1 + dev: false + + /ofetch@1.3.4: + resolution: {integrity: sha512-KLIET85ik3vhEfS+3fDlc/BAZiAp+43QEC/yCo5zkNoY2YaKvNkOaFr/6wCFgFH1kuYQM5pMNi0Tg8koiIemtw==} + dependencies: + destr: 2.0.3 + node-fetch-native: 1.6.4 + ufo: 1.5.3 + dev: false + + /ohash@1.1.3: + resolution: {integrity: sha512-zuHHiGTYTA1sYJ/wZN+t5HKZaH23i4yI1HMwbuXm24Nid7Dv0KcuRlKoNKS9UNfAVSBlnGLcuQrnOKWOZoEGaw==} + dev: false + + /on-exit-leak-free@0.2.0: + resolution: {integrity: sha512-dqaz3u44QbRXQooZLTUKU41ZrzYrcvLISVgbrzbyCMxpmSLJvZ3ZamIJIZ29P6OhZIkNIQKosdeM6t1LYbA9hg==} + dev: false + /once@1.4.0: resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} requiresBuild: true dependencies: wrappy: 1.0.2 dev: false - optional: true /onetime@5.1.2: resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==} @@ -2331,6 +4150,13 @@ packages: mimic-fn: 2.1.0 dev: false + /onetime@6.0.0: + resolution: {integrity: sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==} + engines: {node: '>=12'} + dependencies: + mimic-fn: 4.0.0 + dev: false + /ora@5.4.1: resolution: {integrity: sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==} engines: {node: '>=10'} @@ -2346,11 +4172,96 @@ packages: wcwidth: 1.0.1 dev: false + /os-browserify@0.3.0: + resolution: {integrity: sha512-gjcpUc3clBf9+210TRaDWbf+rZZZEshZ+DlXMRCeAjp0xhTrnQsKHypIy1J3d5hKdUzj69t708EHtU8P6bUn0A==} + dev: false + /os-tmpdir@1.0.2: resolution: {integrity: sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==} engines: {node: '>=0.10.0'} dev: false + /p-limit@2.3.0: + resolution: {integrity: sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==} + engines: {node: '>=6'} + dependencies: + p-try: 2.2.0 + dev: false + + /p-limit@3.1.0: + resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} + engines: {node: '>=10'} + dependencies: + yocto-queue: 0.1.0 + dev: false + + /p-locate@3.0.0: + resolution: {integrity: sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==} + engines: {node: '>=6'} + dependencies: + p-limit: 2.3.0 + dev: false + + /p-locate@5.0.0: + resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} + engines: {node: '>=10'} + dependencies: + p-limit: 3.1.0 + dev: false + + /p-try@2.2.0: + resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==} + engines: {node: '>=6'} + dev: false + + /pako@1.0.11: + resolution: {integrity: sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==} + dev: false + + /parse-asn1@5.1.7: + resolution: {integrity: sha512-CTM5kuWR3sx9IFamcl5ErfPl6ea/N8IYwiJ+vpeB2g+1iknv7zBl5uPwbMbRVznRVbrNY6lGuDoE5b30grmbqg==} + engines: {node: '>= 0.10'} + dependencies: + asn1.js: 4.10.1 + browserify-aes: 1.2.0 + evp_bytestokey: 1.0.3 + hash-base: 3.0.4 + pbkdf2: 3.1.2 + safe-buffer: 5.2.1 + dev: false + + /path-browserify@1.0.1: + resolution: {integrity: sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==} + dev: false + + /path-exists@3.0.0: + resolution: {integrity: sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==} + engines: {node: '>=4'} + dev: false + + /path-exists@4.0.0: + resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} + engines: {node: '>=8'} + dev: false + + /path-key@3.1.1: + resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} + engines: {node: '>=8'} + dev: false + + /path-key@4.0.0: + resolution: {integrity: sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==} + engines: {node: '>=12'} + dev: false + + /path-parse@1.0.7: + resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} + dev: false + + /pathe@1.1.2: + resolution: {integrity: sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==} + dev: false + /pbkdf2@3.1.2: resolution: {integrity: sha512-iuh7L6jA7JEGu2WxDwtQP1ddOpaJNC4KlDEFfdQajSGgGPNi4OyDc2R7QnbY2bR9QjBVGwgvTdNJZoE7RaxUMA==} engines: {node: '>=0.12'} @@ -2362,21 +4273,187 @@ packages: sha.js: 2.4.11 dev: false + /picocolors@1.0.1: + resolution: {integrity: sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==} + dev: false + + /picomatch@2.3.1: + resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} + engines: {node: '>=8.6'} + dev: false + + /picomatch@4.0.2: + resolution: {integrity: sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==} + engines: {node: '>=12'} + dev: false + + /pino-abstract-transport@0.5.0: + resolution: {integrity: sha512-+KAgmVeqXYbTtU2FScx1XS3kNyfZ5TrXY07V96QnUSFqo2gAqlvmaxH67Lj7SWazqsMabf+58ctdTcBgnOLUOQ==} + dependencies: + duplexify: 4.1.3 + split2: 4.2.0 + dev: false + + /pino-std-serializers@4.0.0: + resolution: {integrity: sha512-cK0pekc1Kjy5w9V2/n+8MkZwusa6EyyxfeQCB799CQRhRt/CqYKiWs5adeu8Shve2ZNffvfC/7J64A2PJo1W/Q==} + dev: false + + /pino@7.11.0: + resolution: {integrity: sha512-dMACeu63HtRLmCG8VKdy4cShCPKaYDR4youZqoSWLxl5Gu99HUw8bw75thbPv9Nip+H+QYX8o3ZJbTdVZZ2TVg==} + hasBin: true + dependencies: + atomic-sleep: 1.0.0 + fast-redact: 3.5.0 + on-exit-leak-free: 0.2.0 + pino-abstract-transport: 0.5.0 + pino-std-serializers: 4.0.0 + process-warning: 1.0.0 + quick-format-unescaped: 4.0.4 + real-require: 0.1.0 + safe-stable-stringify: 2.4.3 + sonic-boom: 2.8.0 + thread-stream: 0.15.2 + dev: false + + /pkg-dir@5.0.0: + resolution: {integrity: sha512-NPE8TDbzl/3YQYY7CSS228s3g2ollTFnc+Qi3tqmqJp9Vg2ovUpixcJEo2HJScN2Ez+kEaal6y70c0ehqJBJeA==} + engines: {node: '>=10'} + dependencies: + find-up: 5.0.0 + dev: false + + /pkg-types@1.1.1: + resolution: {integrity: sha512-ko14TjmDuQJ14zsotODv7dBlwxKhUKQEhuhmbqo1uCi9BB0Z2alo/wAXg6q1dTR5TyuqYyWhjtfe/Tsh+X28jQ==} + dependencies: + confbox: 0.1.7 + mlly: 1.7.0 + pathe: 1.1.2 + dev: false + + /pngjs@3.4.0: + resolution: {integrity: sha512-NCrCHhWmnQklfH4MtJMRjZ2a8c80qXeMlQMv2uVp9ISJMTt562SbGd6n2oq0PaPgKm7Z6pL9E2UlLIhC+SHL3w==} + engines: {node: '>=4.0.0'} + dev: false + /possible-typed-array-names@1.0.0: resolution: {integrity: sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==} engines: {node: '>= 0.4'} dev: false + /postcss@8.4.38: + resolution: {integrity: sha512-Wglpdk03BSfXkHoQa3b/oulrotAkwrlLDRSOb9D0bN86FdRyE9lppSp33aHNPgBa0JKCoB+drFLZkQoRRYae5A==} + engines: {node: ^10 || ^12 || >=14} + dependencies: + nanoid: 3.3.7 + picocolors: 1.0.1 + source-map-js: 1.2.0 + dev: false + + /preact@10.4.1: + resolution: {integrity: sha512-WKrRpCSwL2t3tpOOGhf2WfTpcmbpxaWtDbdJdKdjd0aEiTkvOmS4NBkG6kzlaAHI9AkQ3iVqbFWM3Ei7mZ4o1Q==} + dev: false + + /process-nextick-args@2.0.1: + resolution: {integrity: sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==} + dev: false + + /process-warning@1.0.0: + resolution: {integrity: sha512-du4wfLyj4yCZq1VupnVSZmRsPJsNuxoDQFdCFHLaYiEbFBD7QE0a+I4D7hOxrVnh78QE/YipFAj9lXHiXocV+Q==} + dev: false + + /process@0.11.10: + resolution: {integrity: sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==} + engines: {node: '>= 0.6.0'} + dev: false + /proxy-from-env@1.1.0: resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==} dev: false + /public-encrypt@4.0.3: + resolution: {integrity: sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q==} + dependencies: + bn.js: 4.12.0 + browserify-rsa: 4.1.0 + create-hash: 1.2.0 + parse-asn1: 5.1.7 + randombytes: 2.1.0 + safe-buffer: 5.2.1 + dev: false + + /punycode@1.4.1: + resolution: {integrity: sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ==} + dev: false + + /qrcode@1.4.4: + resolution: {integrity: sha512-oLzEC5+NKFou9P0bMj5+v6Z40evexeE29Z9cummZXZ9QXyMr3lphkURzxjXgPJC5azpxcshoDWV1xE46z+/c3Q==} + engines: {node: '>=4'} + hasBin: true + dependencies: + buffer: 5.7.1 + buffer-alloc: 1.2.0 + buffer-from: 1.1.2 + dijkstrajs: 1.0.3 + isarray: 2.0.5 + pngjs: 3.4.0 + yargs: 13.3.2 + dev: false + + /qs@6.12.1: + resolution: {integrity: sha512-zWmv4RSuB9r2mYQw3zxQuHWeU+42aKi1wWig/j4ele4ygELZ7PEO6MM7rim9oAQH2A5MWfsAVf/jPvTPgCbvUQ==} + engines: {node: '>=0.6'} + dependencies: + side-channel: 1.0.6 + dev: false + + /query-string@7.1.3: + resolution: {integrity: sha512-hh2WYhq4fi8+b+/2Kg9CEge4fDPvHS534aOOvOZeQ3+Vf2mCFsaFBYj0i+iXcAq6I9Vzp5fjMFBlONvayDC1qg==} + engines: {node: '>=6'} + dependencies: + decode-uri-component: 0.2.2 + filter-obj: 1.1.0 + split-on-first: 1.1.0 + strict-uri-encode: 2.0.0 + dev: false + + /querystring-es3@0.2.1: + resolution: {integrity: sha512-773xhDQnZBMFobEiztv8LIl70ch5MSF/jUQVlhwFyBILqq96anmoctVIYz+ZRp0qbCKATTn6ev02M3r7Ga5vqA==} + engines: {node: '>=0.4.x'} + dev: false + + /quick-format-unescaped@4.0.4: + resolution: {integrity: sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg==} + dev: false + + /radix3@1.1.2: + resolution: {integrity: sha512-b484I/7b8rDEdSDKckSSBA8knMpcdsXudlE/LNL639wFoHKwLbEkQFZHWEYwDC0wa0FKUcCY+GAF73Z7wxNVFA==} + dev: false + /randombytes@2.1.0: resolution: {integrity: sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==} dependencies: safe-buffer: 5.2.1 dev: false + /randomfill@1.0.4: + resolution: {integrity: sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==} + dependencies: + randombytes: 2.1.0 + safe-buffer: 5.2.1 + dev: false + + /readable-stream@2.3.8: + resolution: {integrity: sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==} + dependencies: + core-util-is: 1.0.3 + inherits: 2.0.4 + isarray: 1.0.0 + process-nextick-args: 2.0.1 + safe-buffer: 5.1.2 + string_decoder: 1.1.1 + util-deprecate: 1.0.2 + dev: false + /readable-stream@3.6.2: resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==} engines: {node: '>= 6'} @@ -2386,10 +4463,40 @@ packages: util-deprecate: 1.0.2 dev: false + /readdirp@3.6.0: + resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} + engines: {node: '>=8.10.0'} + dependencies: + picomatch: 2.3.1 + dev: false + + /real-require@0.1.0: + resolution: {integrity: sha512-r/H9MzAWtrv8aSVjPCMFpDMl5q66GqtmmRkRjpHTsp4zBAa+snZyiQNlMONiUmEJcsnaw0wCauJ2GWODr/aFkg==} + engines: {node: '>= 12.13.0'} + dev: false + /regenerator-runtime@0.14.1: resolution: {integrity: sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==} dev: false + /require-directory@2.1.1: + resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} + engines: {node: '>=0.10.0'} + dev: false + + /require-main-filename@2.0.0: + resolution: {integrity: sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==} + dev: false + + /resolve@1.22.8: + resolution: {integrity: sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==} + hasBin: true + dependencies: + is-core-module: 2.13.1 + path-parse: 1.0.7 + supports-preserve-symlinks-flag: 1.0.0 + dev: false + /restore-cursor@3.1.0: resolution: {integrity: sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==} engines: {node: '>=8'} @@ -2410,6 +4517,32 @@ packages: inherits: 2.0.4 dev: false + /rollup@4.17.2: + resolution: {integrity: sha512-/9ClTJPByC0U4zNLowV1tMBe8yMEAxewtR3cUNX5BoEpGH3dQEWpJLr6CLp0fPdYRF/fzVOgvDb1zXuakwF5kQ==} + engines: {node: '>=18.0.0', npm: '>=8.0.0'} + hasBin: true + dependencies: + '@types/estree': 1.0.5 + optionalDependencies: + '@rollup/rollup-android-arm-eabi': 4.17.2 + '@rollup/rollup-android-arm64': 4.17.2 + '@rollup/rollup-darwin-arm64': 4.17.2 + '@rollup/rollup-darwin-x64': 4.17.2 + '@rollup/rollup-linux-arm-gnueabihf': 4.17.2 + '@rollup/rollup-linux-arm-musleabihf': 4.17.2 + '@rollup/rollup-linux-arm64-gnu': 4.17.2 + '@rollup/rollup-linux-arm64-musl': 4.17.2 + '@rollup/rollup-linux-powerpc64le-gnu': 4.17.2 + '@rollup/rollup-linux-riscv64-gnu': 4.17.2 + '@rollup/rollup-linux-s390x-gnu': 4.17.2 + '@rollup/rollup-linux-x64-gnu': 4.17.2 + '@rollup/rollup-linux-x64-musl': 4.17.2 + '@rollup/rollup-win32-arm64-msvc': 4.17.2 + '@rollup/rollup-win32-ia32-msvc': 4.17.2 + '@rollup/rollup-win32-x64-msvc': 4.17.2 + fsevents: 2.3.3 + dev: false + /rpc-websockets@7.11.0: resolution: {integrity: sha512-IkLYjayPv6Io8C/TdCL5gwgzd1hFz2vmBZrjMw/SPEXo51ETOhnzgS4Qy5GWi2JQN7HKHa66J3+2mv0fgNh/7w==} dependencies: @@ -2432,10 +4565,19 @@ packages: tslib: 2.6.2 dev: false + /safe-buffer@5.1.2: + resolution: {integrity: sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==} + dev: false + /safe-buffer@5.2.1: resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} dev: false + /safe-stable-stringify@2.4.3: + resolution: {integrity: sha512-e2bDA2WJT0wxseVd4lsDP4+3ONX6HpMXQa1ZhFQ7SU+GjvORCmShbCMltrtIDfkYhVHrOcPtj+KhmDBdPdZD1g==} + engines: {node: '>=10'} + dev: false + /safer-buffer@2.1.2: resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} dev: false @@ -2454,6 +4596,10 @@ packages: node-gyp-build: 4.8.1 dev: false + /set-blocking@2.0.0: + resolution: {integrity: sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==} + dev: false + /set-function-length@1.2.2: resolution: {integrity: sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==} engines: {node: '>= 0.4'} @@ -2466,6 +4612,10 @@ packages: has-property-descriptors: 1.0.2 dev: false + /setimmediate@1.0.5: + resolution: {integrity: sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==} + dev: false + /setprototypeof@1.2.0: resolution: {integrity: sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==} dev: false @@ -2478,21 +4628,107 @@ packages: safe-buffer: 5.2.1 dev: false + /shebang-command@2.0.0: + resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} + engines: {node: '>=8'} + dependencies: + shebang-regex: 3.0.0 + dev: false + + /shebang-regex@3.0.0: + resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} + engines: {node: '>=8'} + dev: false + + /side-channel@1.0.6: + resolution: {integrity: sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.7 + es-errors: 1.3.0 + get-intrinsic: 1.2.4 + object-inspect: 1.13.1 + dev: false + /signal-exit@3.0.7: resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==} dev: false + /signal-exit@4.1.0: + resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} + engines: {node: '>=14'} + dev: false + + /sonic-boom@2.8.0: + resolution: {integrity: sha512-kuonw1YOYYNOve5iHdSahXPOK49GqwA+LZhI6Wz/l0rP57iKyXXIHaRagOBHAPmGwJC6od2Z9zgvZ5loSgMlVg==} + dependencies: + atomic-sleep: 1.0.0 + dev: false + + /source-map-js@1.2.0: + resolution: {integrity: sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==} + engines: {node: '>=0.10.0'} + dev: false + + /split-on-first@1.1.0: + resolution: {integrity: sha512-43ZssAJaMusuKWL8sKUBQXHWOpq8d6CfN/u1p4gUzfJkM05C8rxTmYrkIPTXapZpORA6LkkzcUulJ8FqA7Uudw==} + engines: {node: '>=6'} + dev: false + + /split2@4.2.0: + resolution: {integrity: sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==} + engines: {node: '>= 10.x'} + dev: false + /statuses@1.5.0: resolution: {integrity: sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==} engines: {node: '>= 0.6'} dev: false + /std-env@3.7.0: + resolution: {integrity: sha512-JPbdCEQLj1w5GilpiHAx3qJvFndqybBysA3qUOnznweH4QbNYUsW/ea8QzSrnh0vNsezMMw5bcVool8lM0gwzg==} + dev: false + + /stream-browserify@3.0.0: + resolution: {integrity: sha512-H73RAHsVBapbim0tU2JwwOiXUj+fikfiaoYAKHF3VJfA0pe2BCzkhAHBlLG6REzE+2WNZcxOXjK7lkso+9euLA==} + dependencies: + inherits: 2.0.4 + readable-stream: 3.6.2 + dev: false + + /stream-http@3.2.0: + resolution: {integrity: sha512-Oq1bLqisTyK3TSCXpPbT4sdeYNdmyZJv1LxpEm2vu1ZhK89kSE5YXwZc3cWk0MagGaKriBh9mCFbVGtO+vY29A==} + dependencies: + builtin-status-codes: 3.0.0 + inherits: 2.0.4 + readable-stream: 3.6.2 + xtend: 4.0.2 + dev: false + + /stream-shift@1.0.3: + resolution: {integrity: sha512-76ORR0DO1o1hlKwTbi/DM3EXWGf3ZJYO8cXX5RJwnul2DEg2oyoZyjLNoQM8WsvZiFKCRfC1O0J7iCvie3RZmQ==} + dev: false + /stream-transform@2.1.3: resolution: {integrity: sha512-9GHUiM5hMiCi6Y03jD2ARC1ettBXkQBoQAe7nJsPknnI0ow10aXjTnew8QtYQmLjzn974BnmWEAJgCY6ZP1DeQ==} dependencies: mixme: 0.5.10 dev: false + /strict-uri-encode@2.0.0: + resolution: {integrity: sha512-QwiXZgpRcKkhTj2Scnn++4PKtWsH0kpzZ62L2R6c/LUVYv7hVnZqcg2+sMuT6R7Jusu1vviK/MFsu6kNJfWlEQ==} + engines: {node: '>=4'} + dev: false + + /string-width@3.1.0: + resolution: {integrity: sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==} + engines: {node: '>=6'} + dependencies: + emoji-regex: 7.0.3 + is-fullwidth-code-point: 2.0.0 + strip-ansi: 5.2.0 + dev: false + /string-width@4.2.3: resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} engines: {node: '>=8'} @@ -2502,12 +4738,25 @@ packages: strip-ansi: 6.0.1 dev: false + /string_decoder@1.1.1: + resolution: {integrity: sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==} + dependencies: + safe-buffer: 5.1.2 + dev: false + /string_decoder@1.3.0: resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==} dependencies: safe-buffer: 5.2.1 dev: false + /strip-ansi@5.2.0: + resolution: {integrity: sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==} + engines: {node: '>=6'} + dependencies: + ansi-regex: 4.1.1 + dev: false + /strip-ansi@6.0.1: resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} engines: {node: '>=8'} @@ -2515,6 +4764,11 @@ packages: ansi-regex: 5.0.1 dev: false + /strip-final-newline@3.0.0: + resolution: {integrity: sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==} + engines: {node: '>=12'} + dev: false + /strip-hex-prefix@1.0.0: resolution: {integrity: sha512-q8d4ue7JGEiVcypji1bALTos+0pWtyGlivAWyPuTkHzuTCJqrK9sWxYQZUq6Nq3cuyv3bm734IhHvHtGGURU6A==} engines: {node: '>=6.5.0', npm: '>=3'} @@ -2533,14 +4787,37 @@ packages: has-flag: 4.0.0 dev: false + /supports-preserve-symlinks-flag@1.0.0: + resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} + engines: {node: '>= 0.4'} + dev: false + + /system-architecture@0.1.0: + resolution: {integrity: sha512-ulAk51I9UVUyJgxlv9M6lFot2WP3e7t8Kz9+IS6D4rVba1tR9kON+Ey69f+1R4Q8cd45Lod6a4IcJIxnzGc/zA==} + engines: {node: '>=18'} + dev: false + /text-encoding-utf-8@1.0.2: resolution: {integrity: sha512-8bw4MY9WjdsD2aMtO0OzOCY3pXGYNx2d2FfHRVUKkiCPDWjKuOlhLVASS+pD7VkLTVjW268LYJHwsnPFlBpbAg==} dev: false + /thread-stream@0.15.2: + resolution: {integrity: sha512-UkEhKIg2pD+fjkHQKyJO3yoIvAP3N6RlNFt2dUhcS1FGvCD1cQa1M/PGknCLFIyZdtJOWQjejp7bdNqmN7zwdA==} + dependencies: + real-require: 0.1.0 + dev: false + /through@2.3.8: resolution: {integrity: sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==} dev: false + /timers-browserify@2.0.12: + resolution: {integrity: sha512-9phl76Cqm6FhSX9Xe1ZUAMLtm1BLkKj2Qd5ApyWkXzsMRaA7dgr81kf4wJmQf/hAvg8EEyJxDo3du/0KlhPiKQ==} + engines: {node: '>=0.6.0'} + dependencies: + setimmediate: 1.0.5 + dev: false + /tmp-promise@3.0.3: resolution: {integrity: sha512-RwM7MoPojPxsOBYnyd2hy0bxtIlVrihNs9pj5SUvY8Zz1sQcQG2tG1hSr8PDxfgEB8RNKDhqbIlroIarSNDNsQ==} requiresBuild: true @@ -2563,6 +4840,17 @@ packages: dev: false optional: true + /to-regex-range@5.0.1: + resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} + engines: {node: '>=8.0'} + dependencies: + is-number: 7.0.0 + dev: false + + /toggle-selection@1.0.6: + resolution: {integrity: sha512-BiZS+C1OS8g/q2RRbJmy59xpyghNBqrr6k5L/uKBGRsTfxmu3ffiRnd8mlGPUVayg8pvfi5urfnu8TU7DVOkLQ==} + dev: false + /toidentifier@1.0.1: resolution: {integrity: sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==} engines: {node: '>=0.6'} @@ -2577,10 +4865,18 @@ packages: engines: {node: '>=0.6'} dev: false + /tslib@1.14.1: + resolution: {integrity: sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==} + dev: false + /tslib@2.6.2: resolution: {integrity: sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==} dev: false + /tty-browserify@0.0.1: + resolution: {integrity: sha512-C3TaO7K81YvjCgQH9Q1S3R3P3BtN3RIM8n+OvX4il1K1zgE8ZhI0op7kClgkxtutIE8hQrcrHBXvIheqKUUCxw==} + dev: false + /tweetnacl@1.0.3: resolution: {integrity: sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw==} dev: false @@ -2594,10 +4890,117 @@ packages: resolution: {integrity: sha512-7sI4e/bZijOzyURng88oOFZCISQPTHozfE2sUu5AviFYk5QV7fYGb6YiDl+vKjF/pICA354JImBImL9XJWUvdQ==} dev: false + /ufo@1.5.3: + resolution: {integrity: sha512-Y7HYmWaFwPUmkoQCUIAYpKqkOf+SbVj/2fJJZ4RJMCfZp0rTGwRbzQD+HghfnhKOjL9E01okqz+ncJskGYfBNw==} + dev: false + + /uint8arrays@3.1.0: + resolution: {integrity: sha512-ei5rfKtoRO8OyOIor2Rz5fhzjThwIHJZ3uyDPnDHTXbP0aMQ1RN/6AI5B5d9dBxJOU+BvOAk7ZQ1xphsX8Lrog==} + dependencies: + multiformats: 9.9.0 + dev: false + + /uncrypto@0.1.3: + resolution: {integrity: sha512-Ql87qFHB3s/De2ClA9e0gsnS6zXG27SkTiSJwjCc9MebbfapQfuPzumMIUMi38ezPZVNFcHI9sUIepeQfw8J8Q==} + dev: false + /undici-types@5.26.5: resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==} dev: false + /unenv@1.9.0: + resolution: {integrity: sha512-QKnFNznRxmbOF1hDgzpqrlIf6NC5sbZ2OJ+5Wl3OX8uM+LUJXbj4TXvLJCtwbPTmbMHCLIz6JLKNinNsMShK9g==} + dependencies: + consola: 3.2.3 + defu: 6.1.4 + mime: 3.0.0 + node-fetch-native: 1.6.4 + pathe: 1.1.2 + dev: false + + /unfetch@4.2.0: + resolution: {integrity: sha512-F9p7yYCn6cIW9El1zi0HI6vqpeIvBsr3dSuRO6Xuppb1u5rXpCPmMvLSyECLhybr9isec8Ohl0hPekMVrEinDA==} + dev: false + + /unstorage@1.10.2(idb-keyval@6.2.1): + resolution: {integrity: sha512-cULBcwDqrS8UhlIysUJs2Dk0Mmt8h7B0E6mtR+relW9nZvsf/u4SkAYyNliPiPW7XtFNb5u3IUMkxGxFTTRTgQ==} + peerDependencies: + '@azure/app-configuration': ^1.5.0 + '@azure/cosmos': ^4.0.0 + '@azure/data-tables': ^13.2.2 + '@azure/identity': ^4.0.1 + '@azure/keyvault-secrets': ^4.8.0 + '@azure/storage-blob': ^12.17.0 + '@capacitor/preferences': ^5.0.7 + '@netlify/blobs': ^6.5.0 || ^7.0.0 + '@planetscale/database': ^1.16.0 + '@upstash/redis': ^1.28.4 + '@vercel/kv': ^1.0.1 + idb-keyval: ^6.2.1 + ioredis: ^5.3.2 + peerDependenciesMeta: + '@azure/app-configuration': + optional: true + '@azure/cosmos': + optional: true + '@azure/data-tables': + optional: true + '@azure/identity': + optional: true + '@azure/keyvault-secrets': + optional: true + '@azure/storage-blob': + optional: true + '@capacitor/preferences': + optional: true + '@netlify/blobs': + optional: true + '@planetscale/database': + optional: true + '@upstash/redis': + optional: true + '@vercel/kv': + optional: true + idb-keyval: + optional: true + ioredis: + optional: true + dependencies: + anymatch: 3.1.3 + chokidar: 3.6.0 + destr: 2.0.3 + h3: 1.11.1 + idb-keyval: 6.2.1 + listhen: 1.7.2 + lru-cache: 10.2.2 + mri: 1.2.0 + node-fetch-native: 1.6.4 + ofetch: 1.3.4 + ufo: 1.5.3 + transitivePeerDependencies: + - uWebSockets.js + dev: false + + /untun@0.1.3: + resolution: {integrity: sha512-4luGP9LMYszMRZwsvyUd9MrxgEGZdZuZgpVQHEEX0lCYFESasVRvZd0EYpCkOIbJKHMuv0LskpXc/8Un+MJzEQ==} + hasBin: true + dependencies: + citty: 0.1.6 + consola: 3.2.3 + pathe: 1.1.2 + dev: false + + /uqr@0.1.2: + resolution: {integrity: sha512-MJu7ypHq6QasgF5YRTjqscSzQp/W11zoUk6kvmlH+fmWEs63Y0Eib13hYFwAzagRJcVY8WVnlV+eBDUGMJ5IbA==} + dev: false + + /url@0.11.3: + resolution: {integrity: sha512-6hxOLGfZASQK/cijlZnZJTq8OXAkt/3YGfQX45vvMYXpZoo8NdWZcY73K108Jf759lS1Bv/8wXnHDTSz17dSRw==} + dependencies: + punycode: 1.4.1 + qs: 6.12.1 + dev: false + /utf-8-validate@5.0.10: resolution: {integrity: sha512-Z6czzLq4u8fPOyx7TU6X3dvUZVvoJmxSQ+IcrlmagKhilxlhZgxPK6C5Jqbkw1IDUmFTM+cz9QDnnLTwDz/2gQ==} engines: {node: '>=6.14.2'} @@ -2634,10 +5037,61 @@ packages: hasBin: true dev: false + /vite-plugin-node-polyfills@0.21.0(vite@5.2.11): + resolution: {integrity: sha512-Sk4DiKnmxN8E0vhgEhzLudfJQfaT8k4/gJ25xvUPG54KjLJ6HAmDKbr4rzDD/QWEY+Lwg80KE85fGYBQihEPQA==} + peerDependencies: + vite: ^2.0.0 || ^3.0.0 || ^4.0.0 || ^5.0.0 + dependencies: + '@rollup/plugin-inject': 5.0.5 + node-stdlib-browser: 1.2.0 + vite: 5.2.11 + transitivePeerDependencies: + - rollup + dev: false + + /vite@5.2.11: + resolution: {integrity: sha512-HndV31LWW05i1BLPMUCE1B9E9GFbOu1MbenhS58FuK6owSO5qHm7GiCotrNY1YE5rMeQSFBGmT5ZaLEjFizgiQ==} + engines: {node: ^18.0.0 || >=20.0.0} + hasBin: true + peerDependencies: + '@types/node': ^18.0.0 || >=20.0.0 + less: '*' + lightningcss: ^1.21.0 + sass: '*' + stylus: '*' + sugarss: '*' + terser: ^5.4.0 + peerDependenciesMeta: + '@types/node': + optional: true + less: + optional: true + lightningcss: + optional: true + sass: + optional: true + stylus: + optional: true + sugarss: + optional: true + terser: + optional: true + dependencies: + esbuild: 0.20.2 + postcss: 8.4.38 + rollup: 4.17.2 + optionalDependencies: + fsevents: 2.3.3 + dev: false + /vlq@2.0.4: resolution: {integrity: sha512-aodjPa2wPQFkra1G8CzJBTHXhgk3EVSwxSWXNPr1fgdFLUb8kvLV1iEb6rFgasIsjP82HWI6dsb5Io26DDnasA==} dev: false + /vm-browserify@1.1.2: + resolution: {integrity: sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ==} + dev: false + /wcwidth@1.0.1: resolution: {integrity: sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==} dependencies: @@ -2703,6 +5157,10 @@ packages: webidl-conversions: 3.0.1 dev: false + /which-module@2.0.1: + resolution: {integrity: sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==} + dev: false + /which-typed-array@1.1.15: resolution: {integrity: sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA==} engines: {node: '>= 0.4'} @@ -2714,6 +5172,23 @@ packages: has-tostringtag: 1.0.2 dev: false + /which@2.0.2: + resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} + engines: {node: '>= 8'} + hasBin: true + dependencies: + isexe: 2.0.0 + dev: false + + /wrap-ansi@5.1.0: + resolution: {integrity: sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==} + engines: {node: '>=6'} + dependencies: + ansi-styles: 3.2.1 + string-width: 3.1.0 + strip-ansi: 5.2.0 + dev: false + /wrap-ansi@6.2.0: resolution: {integrity: sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==} engines: {node: '>=8'} @@ -2727,7 +5202,6 @@ packages: resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} requiresBuild: true dev: false - optional: true /ws@7.4.6: resolution: {integrity: sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A==} @@ -2771,6 +5245,42 @@ packages: utf-8-validate: 5.0.10 dev: false + /xtend@4.0.2: + resolution: {integrity: sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==} + engines: {node: '>=0.4'} + dev: false + + /y18n@4.0.3: + resolution: {integrity: sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==} + dev: false + + /yargs-parser@13.1.2: + resolution: {integrity: sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==} + dependencies: + camelcase: 5.3.1 + decamelize: 1.2.0 + dev: false + + /yargs@13.3.2: + resolution: {integrity: sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==} + dependencies: + cliui: 5.0.0 + find-up: 3.0.0 + get-caller-file: 2.0.5 + require-directory: 2.1.1 + require-main-filename: 2.0.0 + set-blocking: 2.0.0 + string-width: 3.1.0 + which-module: 2.0.1 + y18n: 4.0.3 + yargs-parser: 13.1.2 + dev: false + + /yocto-queue@0.1.0: + resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} + engines: {node: '>=10'} + dev: false + /zod@3.22.4: resolution: {integrity: sha512-iC+8Io04lddc+mVqQ9AZ7OQ2MrUKGN+oIQyq1vemgt46jwCwLfhq7/pwnBnNXXXZb8VTVLKwp9EDkx+ryxIWmg==} dev: false diff --git a/packages/networks/solana/src/browser/adapters/WalletConnect.ts b/packages/networks/solana/src/browser/adapters/WalletConnect.ts new file mode 100644 index 0000000..3b945ff --- /dev/null +++ b/packages/networks/solana/src/browser/adapters/WalletConnect.ts @@ -0,0 +1,79 @@ +import { ErrorTypeEnum, WalletPlatformEnum } from '@multiplechain/types' +import WalletConnectWalletAdapter from '@multiplechain/solana-walletconnect' +import { + WalletAdapterNetwork, + type BaseMessageSignerWalletAdapter +} from '@solana/wallet-adapter-base' +import type { + ProviderInterface, + WalletAdapterInterface, + WalletConnectOps +} from '@multiplechain/types' + +const icon = + 'data:image/svg+xml;base64,PHN2ZyB2ZXJzaW9uPSIxLjEiIGJhc2VQcm9maWxlPSJiYXNpYyIgaWQ9IkxheWVyXzEiCgkgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgeD0iMHB4IiB5PSIwcHgiIHZpZXdCb3g9IjAgMCAzODcuNiAyMzcuNiIKCSB4bWw6c3BhY2U9InByZXNlcnZlIj4KPHBhdGggaWQ9IldhbGxldENvbm5lY3RfMDAwMDAwNzM3MDMwNjM0MzgyMjA2NDI3MzAwMDAwMDI5MTc3MTc1NTIyMzY0NzI0OTZfIiBmaWxsPSIjM0I5OUZDIiBkPSJNNzkuNCw0Ni40CgljNjMuMi02MS45LDE2NS43LTYxLjksMjI4LjksMGw3LjYsNy40YzMuMiwzLjEsMy4yLDguMSwwLDExLjJsLTI2LDI1LjVjLTEuNiwxLjUtNC4xLDEuNS01LjcsMGwtMTAuNS0xMC4zCgljLTQ0LjEtNDMuMi0xMTUuNi00My4yLTE1OS43LDBsLTExLjIsMTFjLTEuNiwxLjUtNC4xLDEuNS01LjcsMEw3MSw2NS44Yy0zLjItMy4xLTMuMi04LjEsMC0xMS4yTDc5LjQsNDYuNHogTTM2Mi4xLDk5LjFsMjMuMiwyMi43CgljMy4yLDMuMSwzLjIsOC4xLDAsMTEuMkwyODAuOCwyMzUuM2MtMy4yLDMuMS04LjMsMy4xLTExLjQsMGMwLDAsMCwwLDAsMGwtNzQuMS03Mi42Yy0wLjgtMC44LTIuMS0wLjgtMi45LDBjMCwwLDAsMCwwLDAKCWwtNzQuMSw3Mi42Yy0zLjIsMy4xLTguMywzLjEtMTEuNCwwYzAsMCwwLDAsMCwwTDIuNCwxMzNjLTMuMi0zLjEtMy4yLTguMSwwLTExLjJsMjMuMi0yMi43YzMuMi0zLjEsOC4zLTMuMSwxMS40LDBsNzQuMSw3Mi42CgljMC44LDAuOCwyLjEsMC44LDIuOSwwYzAsMCwwLDAsMCwwbDc0LjEtNzIuNmMzLjItMy4xLDguMy0zLjEsMTEuNCwwYzAsMCwwLDAsMCwwbDc0LjEsNzIuNmMwLjgsMC44LDIuMSwwLjgsMi45LDBsNzQuMS03Mi42CglDMzUzLjgsOTYsMzU4LjksOTYsMzYyLjEsOTkuMXoiLz4KPC9zdmc+' + +let isConnected = false + +const WalletConnect: WalletAdapterInterface = { + icon, + id: 'walletconnect', + name: 'WalletConnect', + platforms: [WalletPlatformEnum.UNIVERSAL], + isDetected: () => true, + isConnected: () => isConnected, + disconnect: async () => { + isConnected = false + Object.keys(localStorage) + .filter((x) => x.startsWith('wc@2')) + .forEach((x) => { + localStorage.removeItem(x) + }) + localStorage.removeItem('walletconnect') + localStorage.removeItem('WALLETCONNECT_DEEPLINK_CHOICE') + indexedDB.deleteDatabase('WALLET_CONNECT_V2_INDEXED_DB') + }, + connect: async ( + provider?: ProviderInterface, + _ops?: WalletConnectOps | object + ): Promise => { + const ops = _ops as WalletConnectOps + + if (provider === undefined) { + throw new Error(ErrorTypeEnum.PROVIDER_IS_REQUIRED) + } + + if (ops === undefined) { + throw new Error(ErrorTypeEnum.OPS_IS_REQUIRED) + } + + if (ops.projectId === undefined) { + throw new Error(ErrorTypeEnum.PROJECT_ID_IS_REQUIRED) + } + + const walletConnect = new WalletConnectWalletAdapter({ + network: provider.isTestnet() + ? WalletAdapterNetwork.Devnet + : WalletAdapterNetwork.Mainnet, + options: { + projectId: ops.projectId, + relayUrl: 'wss://relay.walletconnect.com', + qrcodeModalOptions: { + mobileLinks: ['trust'], + desktopLinks: [ + // 'zerion', + // 'ledger' + ] + } + } + }) + + await walletConnect.connect() + + isConnected = true + + return walletConnect + } +} + +export default WalletConnect diff --git a/packages/networks/solana/src/browser/adapters/index.ts b/packages/networks/solana/src/browser/adapters/index.ts index cb0c6fd..d197bb6 100644 --- a/packages/networks/solana/src/browser/adapters/index.ts +++ b/packages/networks/solana/src/browser/adapters/index.ts @@ -4,4 +4,5 @@ export { default as Solflare } from './Solflare.ts' export { default as TrustWallet } from './TrustWallet.ts' export { default as TokenPocket } from './TokenPocket.ts' export { default as BitgetWallet } from './BitgetWallet.ts' +export { default as WalletConnect } from './WalletConnect.ts' export { default as CoinbaseWallet } from './CoinbaseWallet.ts' From 6f199ad0e1a680ba36bf323fb900c160ff2b7cdd Mon Sep 17 00:00:00 2001 From: Halil Beycan <50718965+BeycanDeveloper@users.noreply.github.com> Date: Tue, 21 May 2024 21:23:59 +0800 Subject: [PATCH 88/90] fixed lint problem --- packages/networks/bitcoin/src/assets/Token.ts | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/packages/networks/bitcoin/src/assets/Token.ts b/packages/networks/bitcoin/src/assets/Token.ts index 8d30a0d..a090488 100644 --- a/packages/networks/bitcoin/src/assets/Token.ts +++ b/packages/networks/bitcoin/src/assets/Token.ts @@ -86,11 +86,7 @@ export class Token extends Contract implements TokenInterface { * @param {number} amount Amount of the tokens that will be used * @returns {Promise} Transaction signer */ - async approve( - owner: string, - spender: string, - amount: number - ): Promise { + async approve(owner: string, spender: string, amount: number): Promise { return new TokenTransactionSigner('example') } } From c98c3bac642cfd6b176ea3e182b0fbd67099f6f7 Mon Sep 17 00:00:00 2001 From: Halil Beycan <50718965+BeycanDeveloper@users.noreply.github.com> Date: Tue, 21 May 2024 22:17:32 +0800 Subject: [PATCH 89/90] if don't have account return 0 --- packages/networks/solana/src/assets/Token.ts | 56 ++++++++++++-------- 1 file changed, 34 insertions(+), 22 deletions(-) diff --git a/packages/networks/solana/src/assets/Token.ts b/packages/networks/solana/src/assets/Token.ts index 10c65ac..4ebe7af 100644 --- a/packages/networks/solana/src/assets/Token.ts +++ b/packages/networks/solana/src/assets/Token.ts @@ -105,13 +105,20 @@ export class Token extends Contract implements TokenInterface { * @returns {Promise} Wallet balance as currency of TOKEN */ async getBalance(owner: string): Promise { - const res = await this.provider.web3.getParsedTokenAccountsByOwner(new PublicKey(owner), { - mint: this.pubKey - }) + try { + const res = await this.provider.web3.getParsedTokenAccountsByOwner( + new PublicKey(owner), + { + mint: this.pubKey + } + ) - return res.value[0] === undefined - ? 0 - : res.value[0].account.data.parsed.info.tokenAmount.uiAmount + return res.value[0] === undefined + ? 0 + : res.value[0].account.data.parsed.info.tokenAmount.uiAmount + } catch (error) { + return 0 + } } /** @@ -127,26 +134,31 @@ export class Token extends Contract implements TokenInterface { * @returns {Promise} Amount of tokens that the spender is allowed to spend */ async getAllowance(owner: string, spender?: string): Promise { - const ownerResult = await this.provider.web3.getParsedTokenAccountsByOwner( - new PublicKey(owner), - { - mint: this.pubKey - } - ) - - if (ownerResult.value[0] === undefined) return 0 + try { + const ownerResult = await this.provider.web3.getParsedTokenAccountsByOwner( + new PublicKey(owner), + { + mint: this.pubKey + } + ) - if (ownerResult.value[0].account.data.parsed.info.delegatedAmount === undefined) return 0 + if (ownerResult.value[0] === undefined) return 0 - if (spender !== undefined) { - if ( - ownerResult.value[0].account.data.parsed.info.delegate.toLowerCase() !== - spender.toLowerCase() - ) + if (ownerResult.value[0].account.data.parsed.info.delegatedAmount === undefined) return 0 - } - return ownerResult.value[0].account.data.parsed.info.delegatedAmount.uiAmount + if (spender !== undefined) { + if ( + ownerResult.value[0].account.data.parsed.info.delegate.toLowerCase() !== + spender.toLowerCase() + ) + return 0 + } + + return ownerResult.value[0].account.data.parsed.info.delegatedAmount.uiAmount + } catch (error) { + return 0 + } } /** From e5ffc1dbed7abbaa29e76e2bbaa0971c6a641439 Mon Sep 17 00:00:00 2001 From: Halil Beycan <50718965+BeycanDeveloper@users.noreply.github.com> Date: Tue, 21 May 2024 22:18:13 +0800 Subject: [PATCH 90/90] start integrate web3modal --- packages/networks/solana/index.html | 8 +- packages/networks/solana/package.json | 2 + packages/networks/solana/pnpm-lock.yaml | 997 ++++++++++++++++-- .../solana/src/browser/adapters/Web3Modal.ts | 185 ++++ .../solana/src/browser/adapters/index.ts | 1 + 5 files changed, 1099 insertions(+), 94 deletions(-) create mode 100644 packages/networks/solana/src/browser/adapters/Web3Modal.ts diff --git a/packages/networks/solana/index.html b/packages/networks/solana/index.html index 41bee00..b6e11ff 100644 --- a/packages/networks/solana/index.html +++ b/packages/networks/solana/index.html @@ -231,7 +231,13 @@ const wallet = new Solana.browser.Wallet(adapter) const adapterProvider = await wallet.connect(provider, { - projectId: '113d9f5689edd84ff230c2a6d679c80c' + projectId: '113d9f5689edd84ff230c2a6d679c80c', + metadata: { + name: 'MultipleChain', + description: 'MultipleChain is a best standard', + url: 'http://localhost:3000/', + icons: [] + } }) document.querySelector('.methods').style.display = 'block' diff --git a/packages/networks/solana/package.json b/packages/networks/solana/package.json index 049bcce..3c7990a 100644 --- a/packages/networks/solana/package.json +++ b/packages/networks/solana/package.json @@ -77,6 +77,8 @@ "@solana/wallet-adapter-tokenpocket": "^0.4.19", "@solana/wallet-adapter-trust": "^0.1.13", "@solana/web3.js": "^1.91.8", + "@web3modal/core": "^4.2.1", + "@web3modal/solana": "^4.2.1", "axios": "^1.6.8" } } \ No newline at end of file diff --git a/packages/networks/solana/pnpm-lock.yaml b/packages/networks/solana/pnpm-lock.yaml index f964a4d..45216c2 100644 --- a/packages/networks/solana/pnpm-lock.yaml +++ b/packages/networks/solana/pnpm-lock.yaml @@ -50,6 +50,12 @@ dependencies: '@solana/web3.js': specifier: ^1.91.8 version: 1.91.8 + '@web3modal/core': + specifier: ^4.2.1 + version: 4.2.1(react@18.3.1) + '@web3modal/solana': + specifier: ^4.2.1 + version: 4.2.1(react@18.3.1) axios: specifier: ^1.6.8 version: 1.6.8(debug@4.3.4) @@ -641,10 +647,50 @@ packages: - utf-8-validate dev: false + /@jnwng/walletconnect-solana@0.2.0(@solana/web3.js@1.91.1): + resolution: {integrity: sha512-nyRq0xLEj9i2J4UXQ0Mr4KzsooTMbLu0ewHOqdQV7iZE0PfbtKa8poTSF4ZBAQD8hoMHEx+I7zGFCNMI9BTrTA==} + peerDependencies: + '@solana/web3.js': ^1.63.0 + dependencies: + '@solana/web3.js': 1.91.1 + '@walletconnect/qrcode-modal': 1.8.0 + '@walletconnect/sign-client': 2.13.0 + '@walletconnect/utils': 2.13.0 + bs58: 5.0.0 + transitivePeerDependencies: + - '@azure/app-configuration' + - '@azure/cosmos' + - '@azure/data-tables' + - '@azure/identity' + - '@azure/keyvault-secrets' + - '@azure/storage-blob' + - '@capacitor/preferences' + - '@netlify/blobs' + - '@planetscale/database' + - '@react-native-async-storage/async-storage' + - '@upstash/redis' + - '@vercel/kv' + - bufferutil + - encoding + - ioredis + - uWebSockets.js + - utf-8-validate + dev: false + /@jridgewell/sourcemap-codec@1.4.15: resolution: {integrity: sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==} dev: false + /@lit-labs/ssr-dom-shim@1.2.0: + resolution: {integrity: sha512-yWJKmpGE6lUURKAaIltoPIE/wrbY3TEkqQt+X0m+7fQNnAv0keydnYvbiJFP1PnMhizmIWRWOG5KLhYyc/xl+g==} + dev: false + + /@lit/reactive-element@2.0.4: + resolution: {integrity: sha512-GFn91inaUa2oHLak8awSIigYz0cU0Payr1rcFsrkf5OJ5eSPxElyZfKh0f2p9FsTiZWXQdWGJeXZICEfXXYSXQ==} + dependencies: + '@lit-labs/ssr-dom-shim': 1.2.0 + dev: false + /@metaplex-foundation/beet-solana@0.3.1: resolution: {integrity: sha512-tgyEl6dvtLln8XX81JyBvWjIiEcjTkUwZbrM5dIobTmoqMuGewSyk9CClno8qsMsFdB5T3jC91Rjeqmu/6xk2g==} dependencies: @@ -1146,6 +1192,7 @@ packages: dependencies: is-glob: 4.0.3 micromatch: 4.0.6 + napi-wasm: 1.1.0 dev: false bundledDependencies: - napi-wasm @@ -1582,6 +1629,30 @@ packages: buffer: 6.0.3 dev: false + /@solana/wallet-adapter-backpack@0.1.14(@solana/web3.js@1.91.1): + resolution: {integrity: sha512-DfNLd5S1P7rmrgqMp+jRd21ryuXUxia1mu4qmZ+cau1NGFO2v5ep14LhzYXmqPde6kgbzPLPkLdRnkffLdI4TA==} + engines: {node: '>=16'} + deprecated: Package no longer supported. Contact Support at https://www.npmjs.com/support for more info. + peerDependencies: + '@solana/web3.js': ^1.77.3 + dependencies: + '@solana/wallet-adapter-base': 0.9.23(@solana/web3.js@1.91.1) + '@solana/web3.js': 1.91.1 + dev: false + + /@solana/wallet-adapter-base@0.9.23(@solana/web3.js@1.91.1): + resolution: {integrity: sha512-apqMuYwFp1jFi55NxDfvXUX2x1T0Zh07MxhZ/nCCTGys5raSfYUh82zen2BLv8BSDj/JxZ2P/s7jrQZGrX8uAw==} + engines: {node: '>=16'} + peerDependencies: + '@solana/web3.js': ^1.77.3 + dependencies: + '@solana/wallet-standard-features': 1.2.0 + '@solana/web3.js': 1.91.1 + '@wallet-standard/base': 1.0.1 + '@wallet-standard/features': 1.0.3 + eventemitter3: 4.0.7 + dev: false + /@solana/wallet-adapter-base@0.9.23(@solana/web3.js@1.91.8): resolution: {integrity: sha512-apqMuYwFp1jFi55NxDfvXUX2x1T0Zh07MxhZ/nCCTGys5raSfYUh82zen2BLv8BSDj/JxZ2P/s7jrQZGrX8uAw==} engines: {node: '>=16'} @@ -1615,6 +1686,16 @@ packages: '@solana/web3.js': 1.91.8 dev: false + /@solana/wallet-adapter-phantom@0.9.24(@solana/web3.js@1.91.1): + resolution: {integrity: sha512-D24AxRHmRJ4AYoRvijbiuUb9LmC4xLGKLMSJS2ly+zGxVmaPASPM/ThaY/DlYTDL31QvkYtl8RzSR4yIU1gpLg==} + engines: {node: '>=16'} + peerDependencies: + '@solana/web3.js': ^1.77.3 + dependencies: + '@solana/wallet-adapter-base': 0.9.23(@solana/web3.js@1.91.1) + '@solana/web3.js': 1.91.1 + dev: false + /@solana/wallet-adapter-phantom@0.9.24(@solana/web3.js@1.91.8): resolution: {integrity: sha512-D24AxRHmRJ4AYoRvijbiuUb9LmC4xLGKLMSJS2ly+zGxVmaPASPM/ThaY/DlYTDL31QvkYtl8RzSR4yIU1gpLg==} engines: {node: '>=16'} @@ -1637,6 +1718,20 @@ packages: bs58: 4.0.1 dev: false + /@solana/wallet-adapter-solflare@0.6.28(@solana/web3.js@1.91.1): + resolution: {integrity: sha512-iiUQtuXp8p4OdruDawsm1dRRnzUCcsu+lKo8OezESskHtbmZw2Ifej0P99AbJbBAcBw7q4GPI6987Vh05Si5rw==} + engines: {node: '>=16'} + peerDependencies: + '@solana/web3.js': ^1.77.3 + dependencies: + '@solana/wallet-adapter-base': 0.9.23(@solana/web3.js@1.91.1) + '@solana/wallet-standard-chains': 1.1.0 + '@solana/web3.js': 1.91.1 + '@solflare-wallet/metamask-sdk': 1.0.3(@solana/web3.js@1.91.1) + '@solflare-wallet/sdk': 1.4.2(@solana/web3.js@1.91.1) + '@wallet-standard/wallet': 1.0.1 + dev: false + /@solana/wallet-adapter-solflare@0.6.28(@solana/web3.js@1.91.8): resolution: {integrity: sha512-iiUQtuXp8p4OdruDawsm1dRRnzUCcsu+lKo8OezESskHtbmZw2Ifej0P99AbJbBAcBw7q4GPI6987Vh05Si5rw==} engines: {node: '>=16'} @@ -1661,6 +1756,16 @@ packages: '@solana/web3.js': 1.91.8 dev: false + /@solana/wallet-adapter-trust@0.1.13(@solana/web3.js@1.91.1): + resolution: {integrity: sha512-lkmPfNdyRgx+z0K7i2cDa3a6SOKXpi3FiaYSo8Zozoxkp+Ga/NXVWxlXtMca4GAc/MnJMVp7yF/31kyFIee+3A==} + engines: {node: '>=16'} + peerDependencies: + '@solana/web3.js': ^1.77.3 + dependencies: + '@solana/wallet-adapter-base': 0.9.23(@solana/web3.js@1.91.1) + '@solana/web3.js': 1.91.1 + dev: false + /@solana/wallet-adapter-trust@0.1.13(@solana/web3.js@1.91.8): resolution: {integrity: sha512-lkmPfNdyRgx+z0K7i2cDa3a6SOKXpi3FiaYSo8Zozoxkp+Ga/NXVWxlXtMca4GAc/MnJMVp7yF/31kyFIee+3A==} engines: {node: '>=16'} @@ -1671,6 +1776,35 @@ packages: '@solana/web3.js': 1.91.8 dev: false + /@solana/wallet-adapter-walletconnect@0.1.16(@solana/web3.js@1.91.1): + resolution: {integrity: sha512-jNaQwSho8hT7gF1ifePE8TJc1FULx8jCF16KX3fZPtzXDxKrj0R4VUpHMGcw4MlDknrnZNLOJAVvyiawAkPCRQ==} + engines: {node: '>=16'} + peerDependencies: + '@solana/web3.js': ^1.77.3 + dependencies: + '@jnwng/walletconnect-solana': 0.2.0(@solana/web3.js@1.91.1) + '@solana/wallet-adapter-base': 0.9.23(@solana/web3.js@1.91.1) + '@solana/web3.js': 1.91.1 + transitivePeerDependencies: + - '@azure/app-configuration' + - '@azure/cosmos' + - '@azure/data-tables' + - '@azure/identity' + - '@azure/keyvault-secrets' + - '@azure/storage-blob' + - '@capacitor/preferences' + - '@netlify/blobs' + - '@planetscale/database' + - '@react-native-async-storage/async-storage' + - '@upstash/redis' + - '@vercel/kv' + - bufferutil + - encoding + - ioredis + - uWebSockets.js + - utf-8-validate + dev: false + /@solana/wallet-standard-chains@1.1.0: resolution: {integrity: sha512-IRJHf94UZM8AaRRmY18d34xCJiVPJej1XVwXiTjihHnmwD0cxdQbc/CKjrawyqFyQAKJx7raE5g9mnJsAdspTg==} engines: {node: '>=16'} @@ -1686,6 +1820,30 @@ packages: '@wallet-standard/features': 1.0.3 dev: false + /@solana/web3.js@1.91.1: + resolution: {integrity: sha512-cPgjZXm688oM9cULvJ8u2VH6Qp5rvptE1N1VODVxn2mAbpZsWrvWNPjmASkMYT/HzyrtqFkPvFdSHg8Xjt7aQA==} + dependencies: + '@babel/runtime': 7.24.5 + '@noble/curves': 1.4.0 + '@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.0 + node-fetch: 2.7.0 + rpc-websockets: 7.11.0 + superstruct: 0.14.2 + transitivePeerDependencies: + - bufferutil + - encoding + - utf-8-validate + dev: false + /@solana/web3.js@1.91.8: resolution: {integrity: sha512-USa6OS1jbh8zOapRJ/CBZImZ8Xb7AJjROZl5adql9TpOoBN9BUzyyouS5oPuZHft7S7eB8uJPuXWYjMi6BHgOw==} dependencies: @@ -1710,6 +1868,19 @@ packages: - utf-8-validate dev: false + /@solflare-wallet/metamask-sdk@1.0.3(@solana/web3.js@1.91.1): + resolution: {integrity: sha512-os5Px5PTMYKGS5tzOoyjDxtOtj0jZKnbI1Uwt8+Jsw1HHIA+Ib2UACCGNhQ/un2f8sIbTfLD1WuucNMOy8KZpQ==} + peerDependencies: + '@solana/web3.js': '*' + dependencies: + '@solana/wallet-standard-features': 1.2.0 + '@solana/web3.js': 1.91.1 + '@wallet-standard/base': 1.0.1 + bs58: 5.0.0 + eventemitter3: 5.0.1 + uuid: 9.0.1 + dev: false + /@solflare-wallet/metamask-sdk@1.0.3(@solana/web3.js@1.91.8): resolution: {integrity: sha512-os5Px5PTMYKGS5tzOoyjDxtOtj0jZKnbI1Uwt8+Jsw1HHIA+Ib2UACCGNhQ/un2f8sIbTfLD1WuucNMOy8KZpQ==} peerDependencies: @@ -1723,6 +1894,17 @@ packages: uuid: 9.0.1 dev: false + /@solflare-wallet/sdk@1.4.2(@solana/web3.js@1.91.1): + resolution: {integrity: sha512-jrseNWipwl9xXZgrzwZF3hhL0eIVxuEtoZOSLmuPuef7FgHjstuTtNJAeT4icA7pzdDV4hZvu54pI2r2f7SmrQ==} + peerDependencies: + '@solana/web3.js': '*' + dependencies: + '@solana/web3.js': 1.91.1 + bs58: 5.0.0 + eventemitter3: 5.0.1 + uuid: 9.0.1 + dev: false + /@solflare-wallet/sdk@1.4.2(@solana/web3.js@1.91.8): resolution: {integrity: sha512-jrseNWipwl9xXZgrzwZF3hhL0eIVxuEtoZOSLmuPuef7FgHjstuTtNJAeT4icA7pzdDV4hZvu54pI2r2f7SmrQ==} peerDependencies: @@ -1879,6 +2061,10 @@ packages: undici-types: 5.26.5 dev: false + /@types/trusted-types@2.0.7: + resolution: {integrity: sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==} + dev: false + /@types/ws@7.4.7: resolution: {integrity: sha512-JQbbmxZTZehdc2iszGKs5oC3NFnjeay7mtAWrdt7qNtAVK0g19muApzAy4bm9byz79xa2ZnO/BOBC2R8RC5Lww==} dependencies: @@ -1920,6 +2106,46 @@ packages: detect-browser: 5.2.0 dev: false + /@walletconnect/core@2.11.2: + resolution: {integrity: sha512-bB4SiXX8hX3/hyBfVPC5gwZCXCl+OPj+/EDVM71iAO3TDsh78KPbrVAbDnnsbHzZVHlsMohtXX3j5XVsheN3+g==} + dependencies: + '@walletconnect/heartbeat': 1.2.1 + '@walletconnect/jsonrpc-provider': 1.0.13 + '@walletconnect/jsonrpc-types': 1.0.3 + '@walletconnect/jsonrpc-utils': 1.0.8 + '@walletconnect/jsonrpc-ws-connection': 1.0.14 + '@walletconnect/keyvaluestorage': 1.1.1 + '@walletconnect/logger': 2.1.2 + '@walletconnect/relay-api': 1.0.10 + '@walletconnect/relay-auth': 1.0.4 + '@walletconnect/safe-json': 1.0.2 + '@walletconnect/time': 1.0.2 + '@walletconnect/types': 2.11.2 + '@walletconnect/utils': 2.11.2 + events: 3.3.0 + isomorphic-unfetch: 3.1.0 + lodash.isequal: 4.5.0 + uint8arrays: 3.1.0 + transitivePeerDependencies: + - '@azure/app-configuration' + - '@azure/cosmos' + - '@azure/data-tables' + - '@azure/identity' + - '@azure/keyvault-secrets' + - '@azure/storage-blob' + - '@capacitor/preferences' + - '@netlify/blobs' + - '@planetscale/database' + - '@react-native-async-storage/async-storage' + - '@upstash/redis' + - '@vercel/kv' + - bufferutil + - encoding + - ioredis + - uWebSockets.js + - utf-8-validate + dev: false + /@walletconnect/core@2.13.0: resolution: {integrity: sha512-blDuZxQenjeXcVJvHxPznTNl6c/2DO4VNrFnus+qHmO6OtT5lZRowdMtlCaCNb1q0OxzgrmBDcTOCbFcCpio/g==} dependencies: @@ -1973,6 +2199,14 @@ packages: tslib: 1.14.1 dev: false + /@walletconnect/heartbeat@1.2.1: + resolution: {integrity: sha512-yVzws616xsDLJxuG/28FqtZ5rzrTA4gUjdEMTbWB5Y8V1XHRmqq4efAxCw5ie7WjbXFSUyBHaWlMR+2/CpQC5Q==} + dependencies: + '@walletconnect/events': 1.0.1 + '@walletconnect/time': 1.0.2 + tslib: 1.14.1 + dev: false + /@walletconnect/heartbeat@1.2.2: resolution: {integrity: sha512-uASiRmC5MwhuRuf05vq4AT48Pq8RMi876zV8rr8cV969uTOzWdB/k+Lj5yI2PBtB1bGQisGen7MM1GcZlQTBXw==} dependencies: @@ -1981,6 +2215,25 @@ packages: events: 3.3.0 dev: false + /@walletconnect/jsonrpc-http-connection@1.0.8: + resolution: {integrity: sha512-+B7cRuaxijLeFDJUq5hAzNyef3e3tBDIxyaCNmFtjwnod5AGis3RToNqzFU33vpVcxFhofkpE7Cx+5MYejbMGw==} + dependencies: + '@walletconnect/jsonrpc-utils': 1.0.8 + '@walletconnect/safe-json': 1.0.2 + cross-fetch: 3.1.8 + events: 3.3.0 + transitivePeerDependencies: + - encoding + dev: false + + /@walletconnect/jsonrpc-provider@1.0.13: + resolution: {integrity: sha512-K73EpThqHnSR26gOyNEL+acEex3P7VWZe6KE12ZwKzAt2H4e5gldZHbjsu2QR9cLeJ8AXuO7kEMOIcRv1QEc7g==} + dependencies: + '@walletconnect/jsonrpc-utils': 1.0.8 + '@walletconnect/safe-json': 1.0.2 + tslib: 1.14.1 + dev: false + /@walletconnect/jsonrpc-provider@1.0.14: resolution: {integrity: sha512-rtsNY1XqHvWj0EtITNeuf8PHMvlCLiS3EjQL+WOkxEOA4KPxsohFnBDeyPYiNm4ZvkQdLnece36opYidmtbmow==} dependencies: @@ -1989,6 +2242,13 @@ packages: events: 3.3.0 dev: false + /@walletconnect/jsonrpc-types@1.0.3: + resolution: {integrity: sha512-iIQ8hboBl3o5ufmJ8cuduGad0CQm3ZlsHtujv9Eu16xq89q+BG7Nh5VLxxUgmtpnrePgFkTwXirCTkwJH1v+Yw==} + dependencies: + keyvaluestorage-interface: 1.0.0 + tslib: 1.14.1 + dev: false + /@walletconnect/jsonrpc-types@1.0.4: resolution: {integrity: sha512-P6679fG/M+wuWg9TY8mh6xFSdYnFyFjwFelxyISxMDrlbXokorEVXYOxiqEbrU3x1BmBoCAJJ+vtEaEoMlpCBQ==} dependencies: @@ -2025,8 +2285,345 @@ packages: optional: true dependencies: '@walletconnect/safe-json': 1.0.2 - idb-keyval: 6.2.1 - unstorage: 1.10.2(idb-keyval@6.2.1) + idb-keyval: 6.2.1 + unstorage: 1.10.2(idb-keyval@6.2.1) + transitivePeerDependencies: + - '@azure/app-configuration' + - '@azure/cosmos' + - '@azure/data-tables' + - '@azure/identity' + - '@azure/keyvault-secrets' + - '@azure/storage-blob' + - '@capacitor/preferences' + - '@netlify/blobs' + - '@planetscale/database' + - '@upstash/redis' + - '@vercel/kv' + - ioredis + - uWebSockets.js + dev: false + + /@walletconnect/logger@2.1.2: + resolution: {integrity: sha512-aAb28I3S6pYXZHQm5ESB+V6rDqIYfsnHaQyzFbwUUBFY4H0OXx/YtTl8lvhUNhMMfb9UxbwEBS253TlXUYJWSw==} + dependencies: + '@walletconnect/safe-json': 1.0.2 + pino: 7.11.0 + dev: false + + /@walletconnect/mobile-registry@1.4.0: + resolution: {integrity: sha512-ZtKRio4uCZ1JUF7LIdecmZt7FOLnX72RPSY7aUVu7mj7CSfxDwUn6gBuK6WGtH+NZCldBqDl5DenI5fFSvkKYw==} + deprecated: 'Deprecated in favor of dynamic registry available from: https://github.com/walletconnect/walletconnect-registry' + dev: false + + /@walletconnect/qrcode-modal@1.8.0: + resolution: {integrity: sha512-BueaFefaAi8mawE45eUtztg3ZFbsAH4DDXh1UNwdUlsvFMjqcYzLUG0xZvDd6z2eOpbgDg2N3bl6gF0KONj1dg==} + deprecated: 'WalletConnect''s v1 SDKs are now deprecated. Please upgrade to a v2 SDK. For details see: https://docs.walletconnect.com/' + dependencies: + '@walletconnect/browser-utils': 1.8.0 + '@walletconnect/mobile-registry': 1.4.0 + '@walletconnect/types': 1.8.0 + copy-to-clipboard: 3.3.3 + preact: 10.4.1 + qrcode: 1.4.4 + dev: false + + /@walletconnect/relay-api@1.0.10: + resolution: {integrity: sha512-tqrdd4zU9VBNqUaXXQASaexklv6A54yEyQQEXYOCr+Jz8Ket0dmPBDyg19LVSNUN2cipAghQc45/KVmfFJ0cYw==} + dependencies: + '@walletconnect/jsonrpc-types': 1.0.4 + dev: false + + /@walletconnect/relay-auth@1.0.4: + resolution: {integrity: sha512-kKJcS6+WxYq5kshpPaxGHdwf5y98ZwbfuS4EE/NkQzqrDFm5Cj+dP8LofzWvjrrLkZq7Afy7WrQMXdLy8Sx7HQ==} + dependencies: + '@stablelib/ed25519': 1.0.3 + '@stablelib/random': 1.0.2 + '@walletconnect/safe-json': 1.0.2 + '@walletconnect/time': 1.0.2 + tslib: 1.14.1 + uint8arrays: 3.1.0 + dev: false + + /@walletconnect/safe-json@1.0.0: + resolution: {integrity: sha512-QJzp/S/86sUAgWY6eh5MKYmSfZaRpIlmCJdi5uG4DJlKkZrHEF7ye7gA+VtbVzvTtpM/gRwO2plQuiooIeXjfg==} + dev: false + + /@walletconnect/safe-json@1.0.2: + resolution: {integrity: sha512-Ogb7I27kZ3LPC3ibn8ldyUr5544t3/STow9+lzz7Sfo808YD7SBWk7SAsdBFlYgP2zDRy2hS3sKRcuSRM0OTmA==} + dependencies: + tslib: 1.14.1 + dev: false + + /@walletconnect/sign-client@2.11.2: + resolution: {integrity: sha512-MfBcuSz2GmMH+P7MrCP46mVE5qhP0ZyWA0FyIH6/WuxQ6G+MgKsGfaITqakpRPsykWOJq8tXMs3XvUPDU413OQ==} + dependencies: + '@walletconnect/core': 2.11.2 + '@walletconnect/events': 1.0.1 + '@walletconnect/heartbeat': 1.2.1 + '@walletconnect/jsonrpc-utils': 1.0.8 + '@walletconnect/logger': 2.1.2 + '@walletconnect/time': 1.0.2 + '@walletconnect/types': 2.11.2 + '@walletconnect/utils': 2.11.2 + events: 3.3.0 + transitivePeerDependencies: + - '@azure/app-configuration' + - '@azure/cosmos' + - '@azure/data-tables' + - '@azure/identity' + - '@azure/keyvault-secrets' + - '@azure/storage-blob' + - '@capacitor/preferences' + - '@netlify/blobs' + - '@planetscale/database' + - '@react-native-async-storage/async-storage' + - '@upstash/redis' + - '@vercel/kv' + - bufferutil + - encoding + - ioredis + - uWebSockets.js + - utf-8-validate + dev: false + + /@walletconnect/sign-client@2.13.0: + resolution: {integrity: sha512-En7KSvNUlQFx20IsYGsFgkNJ2lpvDvRsSFOT5PTdGskwCkUfOpB33SQJ6nCrN19gyoKPNvWg80Cy6MJI0TjNYA==} + dependencies: + '@walletconnect/core': 2.13.0 + '@walletconnect/events': 1.0.1 + '@walletconnect/heartbeat': 1.2.2 + '@walletconnect/jsonrpc-utils': 1.0.8 + '@walletconnect/logger': 2.1.2 + '@walletconnect/time': 1.0.2 + '@walletconnect/types': 2.13.0 + '@walletconnect/utils': 2.13.0 + events: 3.3.0 + transitivePeerDependencies: + - '@azure/app-configuration' + - '@azure/cosmos' + - '@azure/data-tables' + - '@azure/identity' + - '@azure/keyvault-secrets' + - '@azure/storage-blob' + - '@capacitor/preferences' + - '@netlify/blobs' + - '@planetscale/database' + - '@react-native-async-storage/async-storage' + - '@upstash/redis' + - '@vercel/kv' + - bufferutil + - encoding + - ioredis + - uWebSockets.js + - utf-8-validate + dev: false + + /@walletconnect/time@1.0.2: + resolution: {integrity: sha512-uzdd9woDcJ1AaBZRhqy5rNC9laqWGErfc4dxA9a87mPdKOgWMD85mcFo9dIYIts/Jwocfwn07EC6EzclKubk/g==} + dependencies: + tslib: 1.14.1 + dev: false + + /@walletconnect/types@1.8.0: + resolution: {integrity: sha512-Cn+3I0V0vT9ghMuzh1KzZvCkiAxTq+1TR2eSqw5E5AVWfmCtECFkVZBP6uUJZ8YjwLqXheI+rnjqPy7sVM4Fyg==} + deprecated: 'WalletConnect''s v1 SDKs are now deprecated. Please upgrade to a v2 SDK. For details see: https://docs.walletconnect.com/' + dev: false + + /@walletconnect/types@2.11.2: + resolution: {integrity: sha512-p632MFB+lJbip2cvtXPBQslpUdiw1sDtQ5y855bOlAGquay+6fZ4h1DcDePeKQDQM3P77ax2a9aNPZxV6y/h1Q==} + dependencies: + '@walletconnect/events': 1.0.1 + '@walletconnect/heartbeat': 1.2.1 + '@walletconnect/jsonrpc-types': 1.0.3 + '@walletconnect/keyvaluestorage': 1.1.1 + '@walletconnect/logger': 2.1.2 + events: 3.3.0 + transitivePeerDependencies: + - '@azure/app-configuration' + - '@azure/cosmos' + - '@azure/data-tables' + - '@azure/identity' + - '@azure/keyvault-secrets' + - '@azure/storage-blob' + - '@capacitor/preferences' + - '@netlify/blobs' + - '@planetscale/database' + - '@react-native-async-storage/async-storage' + - '@upstash/redis' + - '@vercel/kv' + - ioredis + - uWebSockets.js + dev: false + + /@walletconnect/types@2.12.0: + resolution: {integrity: sha512-uhB3waGmujQVJcPgJvGOpB8RalgYSBT+HpmVbfl4Qe0xJyqpRUo4bPjQa0UYkrHaW20xIw94OuP4+FMLYdeemg==} + dependencies: + '@walletconnect/events': 1.0.1 + '@walletconnect/heartbeat': 1.2.1 + '@walletconnect/jsonrpc-types': 1.0.3 + '@walletconnect/keyvaluestorage': 1.1.1 + '@walletconnect/logger': 2.1.2 + events: 3.3.0 + transitivePeerDependencies: + - '@azure/app-configuration' + - '@azure/cosmos' + - '@azure/data-tables' + - '@azure/identity' + - '@azure/keyvault-secrets' + - '@azure/storage-blob' + - '@capacitor/preferences' + - '@netlify/blobs' + - '@planetscale/database' + - '@react-native-async-storage/async-storage' + - '@upstash/redis' + - '@vercel/kv' + - ioredis + - uWebSockets.js + dev: false + + /@walletconnect/types@2.13.0: + resolution: {integrity: sha512-MWaVT0FkZwzYbD3tvk8F+2qpPlz1LUSWHuqbINUtMXnSzJtXN49Y99fR7FuBhNFtDalfuWsEK17GrNA+KnAsPQ==} + dependencies: + '@walletconnect/events': 1.0.1 + '@walletconnect/heartbeat': 1.2.2 + '@walletconnect/jsonrpc-types': 1.0.4 + '@walletconnect/keyvaluestorage': 1.1.1 + '@walletconnect/logger': 2.1.2 + events: 3.3.0 + transitivePeerDependencies: + - '@azure/app-configuration' + - '@azure/cosmos' + - '@azure/data-tables' + - '@azure/identity' + - '@azure/keyvault-secrets' + - '@azure/storage-blob' + - '@capacitor/preferences' + - '@netlify/blobs' + - '@planetscale/database' + - '@react-native-async-storage/async-storage' + - '@upstash/redis' + - '@vercel/kv' + - ioredis + - uWebSockets.js + dev: false + + /@walletconnect/universal-provider@2.11.2: + resolution: {integrity: sha512-cNtIn5AVoDxKAJ4PmB8m5adnf5mYQMUamEUPKMVvOPscfGtIMQEh9peKsh2AN5xcRVDbgluC01Id545evFyymw==} + dependencies: + '@walletconnect/jsonrpc-http-connection': 1.0.8 + '@walletconnect/jsonrpc-provider': 1.0.13 + '@walletconnect/jsonrpc-types': 1.0.4 + '@walletconnect/jsonrpc-utils': 1.0.8 + '@walletconnect/logger': 2.1.2 + '@walletconnect/sign-client': 2.11.2 + '@walletconnect/types': 2.11.2 + '@walletconnect/utils': 2.11.2 + events: 3.3.0 + transitivePeerDependencies: + - '@azure/app-configuration' + - '@azure/cosmos' + - '@azure/data-tables' + - '@azure/identity' + - '@azure/keyvault-secrets' + - '@azure/storage-blob' + - '@capacitor/preferences' + - '@netlify/blobs' + - '@planetscale/database' + - '@react-native-async-storage/async-storage' + - '@upstash/redis' + - '@vercel/kv' + - bufferutil + - encoding + - ioredis + - uWebSockets.js + - utf-8-validate + dev: false + + /@walletconnect/utils@2.11.2: + resolution: {integrity: sha512-LyfdmrnZY6dWqlF4eDrx5jpUwsB2bEPjoqR5Z6rXPiHJKUOdJt7az+mNOn5KTSOlRpd1DmozrBrWr+G9fFLYVw==} + dependencies: + '@stablelib/chacha20poly1305': 1.0.1 + '@stablelib/hkdf': 1.0.1 + '@stablelib/random': 1.0.2 + '@stablelib/sha256': 1.0.1 + '@stablelib/x25519': 1.0.3 + '@walletconnect/relay-api': 1.0.10 + '@walletconnect/safe-json': 1.0.2 + '@walletconnect/time': 1.0.2 + '@walletconnect/types': 2.11.2 + '@walletconnect/window-getters': 1.0.1 + '@walletconnect/window-metadata': 1.0.1 + detect-browser: 5.3.0 + query-string: 7.1.3 + uint8arrays: 3.1.0 + transitivePeerDependencies: + - '@azure/app-configuration' + - '@azure/cosmos' + - '@azure/data-tables' + - '@azure/identity' + - '@azure/keyvault-secrets' + - '@azure/storage-blob' + - '@capacitor/preferences' + - '@netlify/blobs' + - '@planetscale/database' + - '@react-native-async-storage/async-storage' + - '@upstash/redis' + - '@vercel/kv' + - ioredis + - uWebSockets.js + dev: false + + /@walletconnect/utils@2.12.0: + resolution: {integrity: sha512-GIpfHUe1Bjp1Tjda0SkJEizKOT2biuv7VPFnKsOLT1T+8QxEP9NruC+K2UUEvijS1Qr/LKH9P5004RYNgrch+w==} + dependencies: + '@stablelib/chacha20poly1305': 1.0.1 + '@stablelib/hkdf': 1.0.1 + '@stablelib/random': 1.0.2 + '@stablelib/sha256': 1.0.1 + '@stablelib/x25519': 1.0.3 + '@walletconnect/relay-api': 1.0.10 + '@walletconnect/safe-json': 1.0.2 + '@walletconnect/time': 1.0.2 + '@walletconnect/types': 2.12.0 + '@walletconnect/window-getters': 1.0.1 + '@walletconnect/window-metadata': 1.0.1 + detect-browser: 5.3.0 + query-string: 7.1.3 + uint8arrays: 3.1.0 + transitivePeerDependencies: + - '@azure/app-configuration' + - '@azure/cosmos' + - '@azure/data-tables' + - '@azure/identity' + - '@azure/keyvault-secrets' + - '@azure/storage-blob' + - '@capacitor/preferences' + - '@netlify/blobs' + - '@planetscale/database' + - '@react-native-async-storage/async-storage' + - '@upstash/redis' + - '@vercel/kv' + - ioredis + - uWebSockets.js + dev: false + + /@walletconnect/utils@2.13.0: + resolution: {integrity: sha512-q1eDCsRHj5iLe7fF8RroGoPZpdo2CYMZzQSrw1iqL+2+GOeqapxxuJ1vaJkmDUkwgklfB22ufqG6KQnz78sD4w==} + dependencies: + '@stablelib/chacha20poly1305': 1.0.1 + '@stablelib/hkdf': 1.0.1 + '@stablelib/random': 1.0.2 + '@stablelib/sha256': 1.0.1 + '@stablelib/x25519': 1.0.3 + '@walletconnect/relay-api': 1.0.10 + '@walletconnect/safe-json': 1.0.2 + '@walletconnect/time': 1.0.2 + '@walletconnect/types': 2.13.0 + '@walletconnect/window-getters': 1.0.1 + '@walletconnect/window-metadata': 1.0.1 + detect-browser: 5.3.0 + query-string: 7.1.3 + uint8arrays: 3.1.0 transitivePeerDependencies: - '@azure/app-configuration' - '@azure/cosmos' @@ -2037,75 +2634,73 @@ packages: - '@capacitor/preferences' - '@netlify/blobs' - '@planetscale/database' + - '@react-native-async-storage/async-storage' - '@upstash/redis' - '@vercel/kv' - ioredis - uWebSockets.js dev: false - /@walletconnect/logger@2.1.2: - resolution: {integrity: sha512-aAb28I3S6pYXZHQm5ESB+V6rDqIYfsnHaQyzFbwUUBFY4H0OXx/YtTl8lvhUNhMMfb9UxbwEBS253TlXUYJWSw==} - dependencies: - '@walletconnect/safe-json': 1.0.2 - pino: 7.11.0 + /@walletconnect/window-getters@1.0.0: + resolution: {integrity: sha512-xB0SQsLaleIYIkSsl43vm8EwETpBzJ2gnzk7e0wMF3ktqiTGS6TFHxcprMl5R44KKh4tCcHCJwolMCaDSwtAaA==} dev: false - /@walletconnect/mobile-registry@1.4.0: - resolution: {integrity: sha512-ZtKRio4uCZ1JUF7LIdecmZt7FOLnX72RPSY7aUVu7mj7CSfxDwUn6gBuK6WGtH+NZCldBqDl5DenI5fFSvkKYw==} - deprecated: 'Deprecated in favor of dynamic registry available from: https://github.com/walletconnect/walletconnect-registry' + /@walletconnect/window-getters@1.0.1: + resolution: {integrity: sha512-vHp+HqzGxORPAN8gY03qnbTMnhqIwjeRJNOMOAzePRg4xVEEE2WvYsI9G2NMjOknA8hnuYbU3/hwLcKbjhc8+Q==} + dependencies: + tslib: 1.14.1 dev: false - /@walletconnect/qrcode-modal@1.8.0: - resolution: {integrity: sha512-BueaFefaAi8mawE45eUtztg3ZFbsAH4DDXh1UNwdUlsvFMjqcYzLUG0xZvDd6z2eOpbgDg2N3bl6gF0KONj1dg==} - deprecated: 'WalletConnect''s v1 SDKs are now deprecated. Please upgrade to a v2 SDK. For details see: https://docs.walletconnect.com/' + /@walletconnect/window-metadata@1.0.0: + resolution: {integrity: sha512-9eFvmJxIKCC3YWOL97SgRkKhlyGXkrHwamfechmqszbypFspaSk+t2jQXAEU7YClHF6Qjw5eYOmy1//zFi9/GA==} dependencies: - '@walletconnect/browser-utils': 1.8.0 - '@walletconnect/mobile-registry': 1.4.0 - '@walletconnect/types': 1.8.0 - copy-to-clipboard: 3.3.3 - preact: 10.4.1 - qrcode: 1.4.4 + '@walletconnect/window-getters': 1.0.1 dev: false - /@walletconnect/relay-api@1.0.10: - resolution: {integrity: sha512-tqrdd4zU9VBNqUaXXQASaexklv6A54yEyQQEXYOCr+Jz8Ket0dmPBDyg19LVSNUN2cipAghQc45/KVmfFJ0cYw==} + /@walletconnect/window-metadata@1.0.1: + resolution: {integrity: sha512-9koTqyGrM2cqFRW517BPY/iEtUDx2r1+Pwwu5m7sJ7ka79wi3EyqhqcICk/yDmv6jAS1rjKgTKXlEhanYjijcA==} dependencies: - '@walletconnect/jsonrpc-types': 1.0.4 + '@walletconnect/window-getters': 1.0.1 + tslib: 1.14.1 dev: false - /@walletconnect/relay-auth@1.0.4: - resolution: {integrity: sha512-kKJcS6+WxYq5kshpPaxGHdwf5y98ZwbfuS4EE/NkQzqrDFm5Cj+dP8LofzWvjrrLkZq7Afy7WrQMXdLy8Sx7HQ==} + /@web3modal/common@4.2.1: + resolution: {integrity: sha512-RSx+MKCTr9x8ACTBSIren30goFqkAiplMe4098VNYsYriDjIRyz0mtE8JcM/padrqM+Xvc61xgVx81O15H5drQ==} dependencies: - '@stablelib/ed25519': 1.0.3 - '@stablelib/random': 1.0.2 - '@walletconnect/safe-json': 1.0.2 - '@walletconnect/time': 1.0.2 - tslib: 1.14.1 - uint8arrays: 3.1.0 + bignumber.js: 9.1.2 + dayjs: 1.11.10 dev: false - /@walletconnect/safe-json@1.0.0: - resolution: {integrity: sha512-QJzp/S/86sUAgWY6eh5MKYmSfZaRpIlmCJdi5uG4DJlKkZrHEF7ye7gA+VtbVzvTtpM/gRwO2plQuiooIeXjfg==} + /@web3modal/core@4.2.1(react@18.3.1): + resolution: {integrity: sha512-2Meod0xYxwtnaq6fzZXZOFat2+KhPO/N3y8TBZmN2Xl5DF7/jY/KCFP6/MLdhBEcKXxU5umm3tZ0ASAF7dFzrA==} + dependencies: + '@web3modal/common': 4.2.1 + '@web3modal/wallet': 4.2.1 + valtio: 1.11.2(react@18.3.1) + transitivePeerDependencies: + - '@types/react' + - react dev: false - /@walletconnect/safe-json@1.0.2: - resolution: {integrity: sha512-Ogb7I27kZ3LPC3ibn8ldyUr5544t3/STow9+lzz7Sfo808YD7SBWk7SAsdBFlYgP2zDRy2hS3sKRcuSRM0OTmA==} + /@web3modal/polyfills@4.2.1: + resolution: {integrity: sha512-ejt4Z1kDILTl1h1SjCQbfp69QG5N8eHert0m6uJnjnRedQkGYBN92qzAKDCcGjScZDfH4HOAFznFoNpTJChvrg==} dependencies: - tslib: 1.14.1 + buffer: 6.0.3 dev: false - /@walletconnect/sign-client@2.13.0: - resolution: {integrity: sha512-En7KSvNUlQFx20IsYGsFgkNJ2lpvDvRsSFOT5PTdGskwCkUfOpB33SQJ6nCrN19gyoKPNvWg80Cy6MJI0TjNYA==} + /@web3modal/scaffold-react@4.2.1(react@18.3.1): + resolution: {integrity: sha512-z21kMB2GTeLFqwXQdJsgJHEGiCPmqDpNZ/v/Lirn4sji6H5PSdiRYo4xQrZsjJaPiM7nQbV3qcPeNtKapOXRCA==} + peerDependencies: + react: '>=17' + react-dom: '>=17' + peerDependenciesMeta: + react: + optional: true + react-dom: + optional: true dependencies: - '@walletconnect/core': 2.13.0 - '@walletconnect/events': 1.0.1 - '@walletconnect/heartbeat': 1.2.2 - '@walletconnect/jsonrpc-utils': 1.0.8 - '@walletconnect/logger': 2.1.2 - '@walletconnect/time': 1.0.2 - '@walletconnect/types': 2.13.0 - '@walletconnect/utils': 2.13.0 - events: 3.3.0 + '@web3modal/scaffold': 4.2.1(react@18.3.1) + react: 18.3.1 transitivePeerDependencies: - '@azure/app-configuration' - '@azure/cosmos' @@ -2117,35 +2712,33 @@ packages: - '@netlify/blobs' - '@planetscale/database' - '@react-native-async-storage/async-storage' + - '@types/react' - '@upstash/redis' - '@vercel/kv' - - bufferutil - - encoding - ioredis - uWebSockets.js - - utf-8-validate dev: false - /@walletconnect/time@1.0.2: - resolution: {integrity: sha512-uzdd9woDcJ1AaBZRhqy5rNC9laqWGErfc4dxA9a87mPdKOgWMD85mcFo9dIYIts/Jwocfwn07EC6EzclKubk/g==} + /@web3modal/scaffold-utils@4.2.1(react@18.3.1): + resolution: {integrity: sha512-icycRYtElH5Cj4nZamwfG7Z4V5l+z52saaWsUHf+ectj65I8zAKBvYr3qh4pJ/UoxUIg/wIsX7h1qKscL0poMQ==} dependencies: - tslib: 1.14.1 - dev: false - - /@walletconnect/types@1.8.0: - resolution: {integrity: sha512-Cn+3I0V0vT9ghMuzh1KzZvCkiAxTq+1TR2eSqw5E5AVWfmCtECFkVZBP6uUJZ8YjwLqXheI+rnjqPy7sVM4Fyg==} - deprecated: 'WalletConnect''s v1 SDKs are now deprecated. Please upgrade to a v2 SDK. For details see: https://docs.walletconnect.com/' + '@web3modal/core': 4.2.1(react@18.3.1) + '@web3modal/polyfills': 4.2.1 + valtio: 1.11.2(react@18.3.1) + transitivePeerDependencies: + - '@types/react' + - react dev: false - /@walletconnect/types@2.13.0: - resolution: {integrity: sha512-MWaVT0FkZwzYbD3tvk8F+2qpPlz1LUSWHuqbINUtMXnSzJtXN49Y99fR7FuBhNFtDalfuWsEK17GrNA+KnAsPQ==} + /@web3modal/scaffold-vue@4.2.1(react@18.3.1): + resolution: {integrity: sha512-p6e8UJDHKfeQiZqaCge4+b94aTE1nq2XlkcJ6nORnDWfT8Brkw/FzlJJTSwpAUWBZsqpSjv6hlaPgDVs2SVfXA==} + peerDependencies: + vue: '>=3' + peerDependenciesMeta: + vue: + optional: true dependencies: - '@walletconnect/events': 1.0.1 - '@walletconnect/heartbeat': 1.2.2 - '@walletconnect/jsonrpc-types': 1.0.4 - '@walletconnect/keyvaluestorage': 1.1.1 - '@walletconnect/logger': 2.1.2 - events: 3.3.0 + '@web3modal/scaffold': 4.2.1(react@18.3.1) transitivePeerDependencies: - '@azure/app-configuration' - '@azure/cosmos' @@ -2157,29 +2750,23 @@ packages: - '@netlify/blobs' - '@planetscale/database' - '@react-native-async-storage/async-storage' + - '@types/react' - '@upstash/redis' - '@vercel/kv' - ioredis + - react - uWebSockets.js dev: false - /@walletconnect/utils@2.13.0: - resolution: {integrity: sha512-q1eDCsRHj5iLe7fF8RroGoPZpdo2CYMZzQSrw1iqL+2+GOeqapxxuJ1vaJkmDUkwgklfB22ufqG6KQnz78sD4w==} + /@web3modal/scaffold@4.2.1(react@18.3.1): + resolution: {integrity: sha512-onSjmPu1iTHJdQzVcBiad6MIwey04x5NnGBlz4BZgGcpsvpumNU+I41ELbCqD3+5qEGXGcTncFL6rxBnF/ZqXw==} dependencies: - '@stablelib/chacha20poly1305': 1.0.1 - '@stablelib/hkdf': 1.0.1 - '@stablelib/random': 1.0.2 - '@stablelib/sha256': 1.0.1 - '@stablelib/x25519': 1.0.3 - '@walletconnect/relay-api': 1.0.10 - '@walletconnect/safe-json': 1.0.2 - '@walletconnect/time': 1.0.2 - '@walletconnect/types': 2.13.0 - '@walletconnect/window-getters': 1.0.1 - '@walletconnect/window-metadata': 1.0.1 - detect-browser: 5.3.0 - query-string: 7.1.3 - uint8arrays: 3.1.0 + '@web3modal/common': 4.2.1 + '@web3modal/core': 4.2.1(react@18.3.1) + '@web3modal/siwe': 4.2.1(react@18.3.1) + '@web3modal/ui': 4.2.1 + '@web3modal/wallet': 4.2.1 + lit: 3.1.0 transitivePeerDependencies: - '@azure/app-configuration' - '@azure/cosmos' @@ -2191,33 +2778,105 @@ packages: - '@netlify/blobs' - '@planetscale/database' - '@react-native-async-storage/async-storage' + - '@types/react' - '@upstash/redis' - '@vercel/kv' - ioredis + - react - uWebSockets.js dev: false - /@walletconnect/window-getters@1.0.0: - resolution: {integrity: sha512-xB0SQsLaleIYIkSsl43vm8EwETpBzJ2gnzk7e0wMF3ktqiTGS6TFHxcprMl5R44KKh4tCcHCJwolMCaDSwtAaA==} + /@web3modal/siwe@4.2.1(react@18.3.1): + resolution: {integrity: sha512-9/MYyQf7JdLPJOM4Yv3vJPAAm97ar2cJodatYgl9zB7gWOXI9U9OwoY7Xlds+AT6dTurY4l5qF+S9nBYeYNnXQ==} + dependencies: + '@walletconnect/utils': 2.12.0 + '@web3modal/core': 4.2.1(react@18.3.1) + '@web3modal/scaffold-utils': 4.2.1(react@18.3.1) + lit: 3.1.0 + valtio: 1.11.2(react@18.3.1) + transitivePeerDependencies: + - '@azure/app-configuration' + - '@azure/cosmos' + - '@azure/data-tables' + - '@azure/identity' + - '@azure/keyvault-secrets' + - '@azure/storage-blob' + - '@capacitor/preferences' + - '@netlify/blobs' + - '@planetscale/database' + - '@react-native-async-storage/async-storage' + - '@types/react' + - '@upstash/redis' + - '@vercel/kv' + - ioredis + - react + - uWebSockets.js dev: false - /@walletconnect/window-getters@1.0.1: - resolution: {integrity: sha512-vHp+HqzGxORPAN8gY03qnbTMnhqIwjeRJNOMOAzePRg4xVEEE2WvYsI9G2NMjOknA8hnuYbU3/hwLcKbjhc8+Q==} + /@web3modal/solana@4.2.1(react@18.3.1): + resolution: {integrity: sha512-FvpajoY/HzYKMvzb/4ZTCkqdyUXnMH7ETw/xrM9tEWouSNkpNWg7pW7i7AVgFFz9eFox9JG9WKlE6RVL3vmsiQ==} + peerDependencies: + react: '>=17' + react-dom: '>=17' + vue: '>=3' + peerDependenciesMeta: + react: + optional: true + react-dom: + optional: true + vue: + optional: true dependencies: - tslib: 1.14.1 + '@ethersproject/sha2': 5.7.0 + '@solana/wallet-adapter-backpack': 0.1.14(@solana/web3.js@1.91.1) + '@solana/wallet-adapter-base': 0.9.23(@solana/web3.js@1.91.1) + '@solana/wallet-adapter-phantom': 0.9.24(@solana/web3.js@1.91.1) + '@solana/wallet-adapter-solflare': 0.6.28(@solana/web3.js@1.91.1) + '@solana/wallet-adapter-trust': 0.1.13(@solana/web3.js@1.91.1) + '@solana/wallet-adapter-walletconnect': 0.1.16(@solana/web3.js@1.91.1) + '@solana/web3.js': 1.91.1 + '@walletconnect/universal-provider': 2.11.2 + '@web3modal/polyfills': 4.2.1 + '@web3modal/scaffold': 4.2.1(react@18.3.1) + '@web3modal/scaffold-react': 4.2.1(react@18.3.1) + '@web3modal/scaffold-utils': 4.2.1(react@18.3.1) + '@web3modal/scaffold-vue': 4.2.1(react@18.3.1) + bn.js: 5.2.1 + bs58: 5.0.0 + react: 18.3.1 + transitivePeerDependencies: + - '@azure/app-configuration' + - '@azure/cosmos' + - '@azure/data-tables' + - '@azure/identity' + - '@azure/keyvault-secrets' + - '@azure/storage-blob' + - '@capacitor/preferences' + - '@netlify/blobs' + - '@planetscale/database' + - '@react-native-async-storage/async-storage' + - '@types/react' + - '@upstash/redis' + - '@vercel/kv' + - bufferutil + - encoding + - ioredis + - uWebSockets.js + - utf-8-validate dev: false - /@walletconnect/window-metadata@1.0.0: - resolution: {integrity: sha512-9eFvmJxIKCC3YWOL97SgRkKhlyGXkrHwamfechmqszbypFspaSk+t2jQXAEU7YClHF6Qjw5eYOmy1//zFi9/GA==} + /@web3modal/ui@4.2.1: + resolution: {integrity: sha512-mBoSy8/q9LFw62vpPQDVBo6rcsKaNmp3U7hdzEjTdMsDd0icXxgeaFGtaNu5D6uM/TxKe4UllwcH9Up+7OGlpQ==} dependencies: - '@walletconnect/window-getters': 1.0.1 + lit: 3.1.0 + qrcode: 1.5.3 dev: false - /@walletconnect/window-metadata@1.0.1: - resolution: {integrity: sha512-9koTqyGrM2cqFRW517BPY/iEtUDx2r1+Pwwu5m7sJ7ka79wi3EyqhqcICk/yDmv6jAS1rjKgTKXlEhanYjijcA==} + /@web3modal/wallet@4.2.1: + resolution: {integrity: sha512-O6PAjAHcttdkfUGMp6FN5VAEYjjh/5RycJsqfxlnDcxNVzirYgENROR+xdRL/6auR2sbnofkgIjJBGegyshn2A==} dependencies: - '@walletconnect/window-getters': 1.0.1 - tslib: 1.14.1 + '@web3modal/polyfills': 4.2.1 + zod: 3.22.4 dev: false /JSONStream@1.3.5: @@ -2779,6 +3438,14 @@ packages: wrap-ansi: 5.1.0 dev: false + /cliui@6.0.0: + resolution: {integrity: sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==} + dependencies: + string-width: 4.2.3 + strip-ansi: 6.0.1 + wrap-ansi: 6.2.0 + dev: false + /clone@1.0.4: resolution: {integrity: sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==} engines: {node: '>=0.8'} @@ -2957,6 +3624,10 @@ packages: stream-transform: 2.1.3 dev: false + /dayjs@1.11.10: + resolution: {integrity: sha512-vjAczensTgRcqDERK0SR2XMwsF/tSvnvlv6VcF2GIhg6Sx4yOIt/irsr1RDJsKiIyBzJDpCoXiWWq28MqH2cnQ==} + dev: false + /debug@4.3.4: resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==} engines: {node: '>=6.0'} @@ -3115,6 +3786,10 @@ packages: resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} dev: false + /encode-utf8@1.0.3: + resolution: {integrity: sha512-ucAnuBEhUK4boH2HjVYG5Q2mQyPorvv0u/ocS+zhdw0S8AlHYY+GOFhP1Gio5z4icpP2ivFSvhtFjQi8+T9ppw==} + dev: false + /end-of-stream@1.4.4: resolution: {integrity: sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==} dependencies: @@ -3304,6 +3979,14 @@ packages: locate-path: 3.0.0 dev: false + /find-up@4.1.0: + resolution: {integrity: sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==} + engines: {node: '>=8'} + dependencies: + locate-path: 5.0.0 + path-exists: 4.0.0 + dev: false + /find-up@5.0.0: resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} engines: {node: '>=10'} @@ -3748,6 +4431,10 @@ packages: resolution: {integrity: sha512-PWsmefG6Jkodqt+ePTvBZCSMFgN7Clckjd0O7su3I0+BW2QWUTJNzjktHsztGLhncP2h8mcF9V9Y2Ha59pAViQ==} dev: false + /js-tokens@4.0.0: + resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} + dev: false + /json-bigint@1.0.0: resolution: {integrity: sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ==} dependencies: @@ -3803,6 +4490,28 @@ packages: - uWebSockets.js dev: false + /lit-element@4.0.5: + resolution: {integrity: sha512-iTWskWZEtn9SyEf4aBG6rKT8GABZMrTWop1+jopsEOgEcugcXJGKuX5bEbkq9qfzY+XB4MAgCaSPwnNpdsNQ3Q==} + dependencies: + '@lit-labs/ssr-dom-shim': 1.2.0 + '@lit/reactive-element': 2.0.4 + lit-html: 3.1.3 + dev: false + + /lit-html@3.1.3: + resolution: {integrity: sha512-FwIbqDD8O/8lM4vUZ4KvQZjPPNx7V1VhT7vmRB8RBAO0AU6wuTVdoXiu2CivVjEGdugvcbPNBLtPE1y0ifplHA==} + dependencies: + '@types/trusted-types': 2.0.7 + dev: false + + /lit@3.1.0: + resolution: {integrity: sha512-rzo/hmUqX8zmOdamDAeydfjsGXbbdtAFqMhmocnh2j9aDYqbu0fjXygjCa0T99Od9VQ/2itwaGrjZz/ZELVl7w==} + dependencies: + '@lit/reactive-element': 2.0.4 + lit-element: 4.0.5 + lit-html: 3.1.3 + dev: false + /locate-path@3.0.0: resolution: {integrity: sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==} engines: {node: '>=6'} @@ -3811,6 +4520,13 @@ packages: path-exists: 3.0.0 dev: false + /locate-path@5.0.0: + resolution: {integrity: sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==} + engines: {node: '>=8'} + dependencies: + p-locate: 4.1.0 + dev: false + /locate-path@6.0.0: resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} engines: {node: '>=10'} @@ -3838,6 +4554,13 @@ packages: is-unicode-supported: 0.1.0 dev: false + /loose-envify@1.4.0: + resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==} + hasBin: true + dependencies: + js-tokens: 4.0.0 + dev: false + /lru-cache@10.2.2: resolution: {integrity: sha512-9hp3Vp2/hFQUiIwKo8XCeFVnrg8Pk3TYNPIR7tJADKi5YfcF7vEaK7avFHTlSy3kOKYaJQaalfEo6YuXdceBOQ==} engines: {node: 14 || >=16.14} @@ -3983,6 +4706,10 @@ packages: hasBin: true dev: false + /napi-wasm@1.1.0: + resolution: {integrity: sha512-lHwIAJbmLSjF9VDRm9GoVOy9AGp3aIvkjv+Kvz9h16QR3uSVYH78PNQUnT2U4X53mhlnV2M7wrhibQ3GHicDmg==} + dev: false + /near-hd-key@1.2.1: resolution: {integrity: sha512-SIrthcL5Wc0sps+2e1xGj3zceEa68TgNZDLuCx0daxmfTP7sFTB3/mtE2pYhlFsCxWoMn+JfID5E1NlzvvbRJg==} dependencies: @@ -4202,6 +4929,13 @@ packages: p-limit: 2.3.0 dev: false + /p-locate@4.1.0: + resolution: {integrity: sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==} + engines: {node: '>=8'} + dependencies: + p-limit: 2.3.0 + dev: false + /p-locate@5.0.0: resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} engines: {node: '>=10'} @@ -4335,6 +5069,11 @@ packages: engines: {node: '>=4.0.0'} dev: false + /pngjs@5.0.0: + resolution: {integrity: sha512-40QW5YalBNfQo5yRYmiw7Yz6TKKVr3h6970B2YE+3fQpsWcrbj1PzJgxeJ19DRQjhMbKPIuMY8rFaXc8moolVw==} + engines: {node: '>=10.13.0'} + dev: false + /possible-typed-array-names@1.0.0: resolution: {integrity: sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==} engines: {node: '>= 0.4'} @@ -4366,6 +5105,10 @@ packages: engines: {node: '>= 0.6.0'} dev: false + /proxy-compare@2.5.1: + resolution: {integrity: sha512-oyfc0Tx87Cpwva5ZXezSp5V9vht1c7dZBhvuV/y3ctkgMVUmiAGDVeeB0dKhGSyT0v1ZTEQYpe/RXlBVBNuCLA==} + dev: false + /proxy-from-env@1.1.0: resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==} dev: false @@ -4399,6 +5142,17 @@ packages: yargs: 13.3.2 dev: false + /qrcode@1.5.3: + resolution: {integrity: sha512-puyri6ApkEHYiVl4CFzo1tDkAZ+ATcnbJrJ6RiBM1Fhctdn/ix9MTE3hRph33omisEbC/2fcfemsseiKgBPKZg==} + engines: {node: '>=10.13.0'} + hasBin: true + dependencies: + dijkstrajs: 1.0.3 + encode-utf8: 1.0.3 + pngjs: 5.0.0 + yargs: 15.4.1 + dev: false + /qs@6.12.1: resolution: {integrity: sha512-zWmv4RSuB9r2mYQw3zxQuHWeU+42aKi1wWig/j4ele4ygELZ7PEO6MM7rim9oAQH2A5MWfsAVf/jPvTPgCbvUQ==} engines: {node: '>=0.6'} @@ -4442,6 +5196,13 @@ packages: safe-buffer: 5.2.1 dev: false + /react@18.3.1: + resolution: {integrity: sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==} + engines: {node: '>=0.10.0'} + dependencies: + loose-envify: 1.4.0 + dev: false + /readable-stream@2.3.8: resolution: {integrity: sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==} dependencies: @@ -5001,6 +5762,14 @@ packages: qs: 6.12.1 dev: false + /use-sync-external-store@1.2.0(react@18.3.1): + resolution: {integrity: sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA==} + peerDependencies: + react: ^16.8.0 || ^17.0.0 || ^18.0.0 + dependencies: + react: 18.3.1 + dev: false + /utf-8-validate@5.0.10: resolution: {integrity: sha512-Z6czzLq4u8fPOyx7TU6X3dvUZVvoJmxSQ+IcrlmagKhilxlhZgxPK6C5Jqbkw1IDUmFTM+cz9QDnnLTwDz/2gQ==} engines: {node: '>=6.14.2'} @@ -5037,6 +5806,23 @@ packages: hasBin: true dev: false + /valtio@1.11.2(react@18.3.1): + resolution: {integrity: sha512-1XfIxnUXzyswPAPXo1P3Pdx2mq/pIqZICkWN60Hby0d9Iqb+MEIpqgYVlbflvHdrp2YR/q3jyKWRPJJ100yxaw==} + engines: {node: '>=12.20.0'} + peerDependencies: + '@types/react': '>=16.8' + react: '>=16.8' + peerDependenciesMeta: + '@types/react': + optional: true + react: + optional: true + dependencies: + proxy-compare: 2.5.1 + react: 18.3.1 + use-sync-external-store: 1.2.0(react@18.3.1) + dev: false + /vite-plugin-node-polyfills@0.21.0(vite@5.2.11): resolution: {integrity: sha512-Sk4DiKnmxN8E0vhgEhzLudfJQfaT8k4/gJ25xvUPG54KjLJ6HAmDKbr4rzDD/QWEY+Lwg80KE85fGYBQihEPQA==} peerDependencies: @@ -5261,6 +6047,14 @@ packages: decamelize: 1.2.0 dev: false + /yargs-parser@18.1.3: + resolution: {integrity: sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==} + engines: {node: '>=6'} + dependencies: + camelcase: 5.3.1 + decamelize: 1.2.0 + dev: false + /yargs@13.3.2: resolution: {integrity: sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==} dependencies: @@ -5276,6 +6070,23 @@ packages: yargs-parser: 13.1.2 dev: false + /yargs@15.4.1: + resolution: {integrity: sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==} + engines: {node: '>=8'} + dependencies: + cliui: 6.0.0 + decamelize: 1.2.0 + find-up: 4.1.0 + get-caller-file: 2.0.5 + require-directory: 2.1.1 + require-main-filename: 2.0.0 + set-blocking: 2.0.0 + string-width: 4.2.3 + which-module: 2.0.1 + y18n: 4.0.3 + yargs-parser: 18.1.3 + dev: false + /yocto-queue@0.1.0: resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} engines: {node: '>=10'} diff --git a/packages/networks/solana/src/browser/adapters/Web3Modal.ts b/packages/networks/solana/src/browser/adapters/Web3Modal.ts new file mode 100644 index 0000000..c8dd207 --- /dev/null +++ b/packages/networks/solana/src/browser/adapters/Web3Modal.ts @@ -0,0 +1,185 @@ +import type { Metadata } from '@web3modal/core' +import { solana, solanaDevnet } from '@web3modal/solana/chains' +import { ErrorTypeEnum, WalletPlatformEnum } from '@multiplechain/types' +import type { BaseMessageSignerWalletAdapter } from '@solana/wallet-adapter-base' +import type { ProviderInterface, WalletAdapterInterface } from '@multiplechain/types' +import { + createWeb3Modal, + defaultSolanaConfig, + type Web3ModalOptions, + type Web3Modal as Web3ModalType +} from '@web3modal/solana' + +const icon = + 'data:image/svg+xml;base64,PHN2ZyB2ZXJzaW9uPSIxLjAiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIKIHdpZHRoPSI0MDAuMDAwMDAwcHQiIGhlaWdodD0iNDAwLjAwMDAwMHB0IiB2aWV3Qm94PSIwIDAgNDAwLjAwMDAwMCA0MDAuMDAwMDAwIgogcHJlc2VydmVBc3BlY3RSYXRpbz0ieE1pZFlNaWQgbWVldCI+Cgo8ZyB0cmFuc2Zvcm09InRyYW5zbGF0ZSgwLjAwMDAwMCw0MDAuMDAwMDAwKSBzY2FsZSgwLjEwMDAwMCwtMC4xMDAwMDApIgpmaWxsPSIjMDAwMDAwIiBzdHJva2U9Im5vbmUiPgo8cGF0aCBkPSJNMCAyMDAwIGwwIC0yMDAwIDIwMDAgMCAyMDAwIDAgMCAyMDAwIDAgMjAwMCAtMjAwMCAwIC0yMDAwIDAgMAotMjAwMHogbTIyNjQgNzM2IGMxMjQgLTMyIDI2MSAtOTggMzYzIC0xNzUgOTEgLTY5IDE3MyAtMTUzIDE3MyAtMTc4IDAgLTE3Ci0xODcgLTIwMiAtMjA1IC0yMDMgLTYgMCAtMzEgMjEgLTU1IDQ2IC0yMjcgMjM0IC01NjkgMjk5IC04NTcgMTY0IC03OSAtMzYKLTEzMSAtNzMgLTIxMyAtMTQ5IC0zNiAtMzMgLTcyIC02MCAtODAgLTYxIC0yMCAwIC0yMDAgMTgxIC0yMDAgMjAyIDAgMjQgNDkKNzggMTM2IDE0OCAxMzYgMTA5IDI4MSAxNzkgNDQxIDIxNSAxMDYgMjMgMTE5IDI0IDI2MyAyMCAxMDQgLTMgMTU4IC0xMCAyMzQKLTI5eiBtLTEyODQgLTYwMyBjMTQgLTkgMTMwIC0xMjAgMjU4IC0yNDYgbDIzMyAtMjMxIDU3IDU1IGMzMSAyOSAxNDUgMTQxCjI1MyAyNDYgMTEwIDEwOSAyMDMgMTkzIDIxMyAxOTMgMjAgMCAzOSAtMTggNTIyIC00OTAgMyAtMiA3OCA2OCAxNjcgMTU2IDI3MAoyNjYgMzQ0IDMzNCAzNjIgMzM0IDEwIDAgNTcgLTM5IDEwNiAtODcgNjcgLTY1IDg5IC05MyA4OSAtMTEzIDAgLTIxIC02NiAtOTAKLTM0MSAtMzYwIC0xODggLTE4NCAtMzUwIC0zMzkgLTM2MCAtMzQ0IC0xMSAtNSAtMjcgLTUgLTM4IDAgLTExIDUgLTEyOCAxMTYKLTI2MSAyNDcgLTEzMyAxMzEgLTI0NSAyMzYgLTI0OCAyMzIgLTEzNiAtMTM4IC00OTAgLTQ3MyAtNTA4IC00NzkgLTI4IC0xMQotMTYgLTIyIC00NTEgNDA2IC0yMDMgMTk5IC0yODMgMjg0IC0yODMgMzAwIDAgMjggMTcxIDE5OCAyMDAgMTk4IDMgMCAxNyAtNwozMCAtMTd6Ii8+CjwvZz4KPC9zdmc+Cg==' + +export interface Web3ModalOps extends Web3ModalOptions { + metadata: Metadata +} + +export interface Web3ModalAdapterInterface extends Omit { + connect: ( + provider?: ProviderInterface, + ops?: Web3ModalOps | object + ) => Promise +} + +interface Chain { + rpcUrl: string + explorerUrl: string + currency: string + name: string + chainId: string +} + +let modal: Web3ModalType +let currentNetwork: Chain +let clickedAnyWallet = false +let connectRejectMethod: (reason?: any) => void +let connectResolveMethod: ( + value: BaseMessageSignerWalletAdapter | PromiseLike +) => void + +const web3Modal = (ops: Web3ModalOps): Web3ModalType => { + if (modal !== undefined) { + return modal + } + + const chains = [solana, solanaDevnet] + + const solanaConfig = defaultSolanaConfig({ + chains, + projectId: ops.projectId, + metadata: ops.metadata + }) + + modal = createWeb3Modal({ + chains, + solanaConfig, + metadata: ops.metadata, + projectId: ops.projectId, + themeMode: ops.themeMode, + allowUnsupportedChain: true, + defaultChain: currentNetwork, + customWallets: ops.customWallets, + themeVariables: { + '--w3m-z-index': 999999999999 + } + }) + + modal.subscribeEvents(async (event) => { + if (event.data.event === 'SELECT_WALLET') { + clickedAnyWallet = true + } + if (event.data.event === 'MODAL_CLOSE') { + if (clickedAnyWallet) { + clickedAnyWallet = false + } else { + connectRejectMethod(new Error(ErrorTypeEnum.CLOSED_WALLETCONNECT_MODAL)) + } + } + }) + + modal.subscribeProvider(async (ctx) => { + if (ctx.provider === undefined) { + return + } + + if (`solana:${currentNetwork.chainId}` !== ctx.caipChainId) { + await modal + .switchNetwork({ + id: `solana:${currentNetwork.chainId}`, + name: currentNetwork.name + }) + .catch(() => { + connectRejectMethod(new Error(ErrorTypeEnum.WALLET_CONNECT_REJECTED)) + }) + } + + if (ctx.provider !== undefined && ctx.provider.on === undefined) { + ctx.provider.on = (_eventName: string, _callback: (...args: any[]) => void): void => { + // WalletConnectProvider does not have an on method + } + } + + // @ts-expect-error this provider methods enought for our needs + connectResolveMethod(ctx.provider as BaseMessageSignerWalletAdapter) + }) + + return modal +} + +const Web3Modal: Web3ModalAdapterInterface = { + icon, + id: 'web3modal', + name: 'Web3Modal', + platforms: [WalletPlatformEnum.UNIVERSAL], + isDetected: () => true, + isConnected: () => { + if (modal === undefined) { + return false + } + + return modal.getAddress() !== undefined + }, + disconnect: async () => { + Object.keys(localStorage) + .filter((x) => { + return ( + x.startsWith('wc@2') || + x.startsWith('@w3m') || + x.startsWith('W3M') || + x.startsWith('-walletlink') + ) + }) + .forEach((x) => { + localStorage.removeItem(x) + }) + + indexedDB.deleteDatabase('WALLET_CONNECT_V2_INDEXED_DB') + + if (modal?.disconnect !== undefined) { + modal.disconnect() + } + }, + connect: async ( + provider?: ProviderInterface, + _ops?: Web3ModalOps | object + ): Promise => { + const ops = _ops as Web3ModalOps + + if (provider === undefined) { + throw new Error(ErrorTypeEnum.PROVIDER_IS_REQUIRED) + } + + if (ops === undefined) { + throw new Error(ErrorTypeEnum.OPS_IS_REQUIRED) + } + + if (ops.projectId === undefined) { + throw new Error(ErrorTypeEnum.PROJECT_ID_IS_REQUIRED) + } + + if (ops.metadata === undefined) { + throw new Error(ErrorTypeEnum.METADATA_IS_REQUIRED) + } + + currentNetwork = provider.isTestnet() ? solanaDevnet : solana + + return await new Promise((resolve, reject) => { + try { + const modal = web3Modal(ops) + connectRejectMethod = async (reason) => { + modal.disconnect() + reject(reason) + } + connectResolveMethod = resolve + void modal.open({ view: 'Connect' }) + } catch (error) { + reject(error) + } + }) + } +} + +export default Web3Modal diff --git a/packages/networks/solana/src/browser/adapters/index.ts b/packages/networks/solana/src/browser/adapters/index.ts index d197bb6..4afca6c 100644 --- a/packages/networks/solana/src/browser/adapters/index.ts +++ b/packages/networks/solana/src/browser/adapters/index.ts @@ -1,6 +1,7 @@ export { default as Slope } from './Slope.ts' export { default as Phantom } from './Phantom.ts' export { default as Solflare } from './Solflare.ts' +export { default as Web3Modal } from './Web3Modal.ts' export { default as TrustWallet } from './TrustWallet.ts' export { default as TokenPocket } from './TokenPocket.ts' export { default as BitgetWallet } from './BitgetWallet.ts'