From 67ead1b8287f1df4d9851de34bb91a73592ad0cc Mon Sep 17 00:00:00 2001 From: aankor Date: Sat, 30 Nov 2024 14:11:00 +0100 Subject: [PATCH 1/2] Start making solana tests --- solana/bridge_token_factory/Anchor.toml | 11 - solana/bridge_token_factory/package.json | 4 + solana/bridge_token_factory/pnpm-lock.yaml | 2116 ++++++++++++++++- .../bridge_token_factory/pnpm-workspace.yaml | 1 + solana/bridge_token_factory/tests/Test.toml | 23 + .../tests/assets/common/wormhole.so | Bin 0 -> 973360 bytes .../tests/assets/common/wormhole_bridge.json | 14 + .../assets/common/wormhole_fee_collector.json | 14 + .../tests/assets/main/config.json | 13 + .../tests/assets/main/sequence.json | 13 + .../logMetadata/mplMetadata/metadata.json | 13 + .../user/logMetadata/mplMetadata/mint.json | 13 + .../user/logMetadata/noMetadata/mint.json | 13 + .../tests/initialize/simple/Test.toml | 14 + solana/bridge_token_factory/ts/cli/src/cli.ts | 16 +- ...eTransferNative.ts => finalizeTransfer.ts} | 36 +- .../ts/cli/src/finalizeTransferBridged.ts | 44 - ...{initTransferNative.ts => initTransfer.ts} | 26 +- .../ts/cli/src/initTransferBridged.ts | 36 - .../ts/cli/src/logMetadata.ts | 20 + .../ts/cli/src/registerMint.ts | 40 - .../ts/sdk/src/bridge_token_factory.json | 416 ++-- .../ts/sdk/src/bridge_token_factory.ts | 416 ++-- .../bridge_token_factory/ts/sdk/src/index.ts | 397 ++-- .../ts/tests/.editorconfig | 8 + .../ts/tests/.eslintignore | 1 + .../ts/tests/.eslintrc.json | 3 + .../ts/tests/.prettierrc.js | 3 + .../tests/__tests__/admin/initialize.spec.ts | 49 + .../tests/__tests__/user/logMetadata.spec.ts | 116 + .../ts/tests/jest.config.cjs | 7 + .../ts/tests/package-lock.json | 108 + .../ts/tests/package.json | 41 + .../ts/tests/src/data/admin/index.ts | 3 + .../tests/src/data/admin/initialize/index.ts | 3 + .../tests/src/data/admin/initialize/simple.ts | 12 + .../ts/tests/src/data/common.ts | 126 + .../ts/tests/src/data/index.ts | 11 + .../ts/tests/src/data/main/index.ts | 67 + .../ts/tests/src/data/user/index.ts | 9 + .../tests/src/data/user/logMetadata/index.ts | 10 + .../src/data/user/logMetadata/mplMetadata.ts | 51 + .../src/data/user/logMetadata/noMetadata.ts | 20 + .../ts/tests/src/jestSetup.ts | 22 + .../bridge_token_factory/ts/tests/src/main.ts | 24 + .../ts/tests/tsconfig.json | 11 + 46 files changed, 3656 insertions(+), 758 deletions(-) create mode 100644 solana/bridge_token_factory/tests/Test.toml create mode 100644 solana/bridge_token_factory/tests/assets/common/wormhole.so create mode 100644 solana/bridge_token_factory/tests/assets/common/wormhole_bridge.json create mode 100644 solana/bridge_token_factory/tests/assets/common/wormhole_fee_collector.json create mode 100644 solana/bridge_token_factory/tests/assets/main/config.json create mode 100644 solana/bridge_token_factory/tests/assets/main/sequence.json create mode 100644 solana/bridge_token_factory/tests/assets/user/logMetadata/mplMetadata/metadata.json create mode 100644 solana/bridge_token_factory/tests/assets/user/logMetadata/mplMetadata/mint.json create mode 100644 solana/bridge_token_factory/tests/assets/user/logMetadata/noMetadata/mint.json create mode 100644 solana/bridge_token_factory/tests/initialize/simple/Test.toml rename solana/bridge_token_factory/ts/cli/src/{finalizeTransferNative.ts => finalizeTransfer.ts} (52%) delete mode 100644 solana/bridge_token_factory/ts/cli/src/finalizeTransferBridged.ts rename solana/bridge_token_factory/ts/cli/src/{initTransferNative.ts => initTransfer.ts} (53%) delete mode 100644 solana/bridge_token_factory/ts/cli/src/initTransferBridged.ts create mode 100644 solana/bridge_token_factory/ts/cli/src/logMetadata.ts delete mode 100644 solana/bridge_token_factory/ts/cli/src/registerMint.ts create mode 100644 solana/bridge_token_factory/ts/tests/.editorconfig create mode 100644 solana/bridge_token_factory/ts/tests/.eslintignore create mode 100644 solana/bridge_token_factory/ts/tests/.eslintrc.json create mode 100644 solana/bridge_token_factory/ts/tests/.prettierrc.js create mode 100644 solana/bridge_token_factory/ts/tests/__tests__/admin/initialize.spec.ts create mode 100644 solana/bridge_token_factory/ts/tests/__tests__/user/logMetadata.spec.ts create mode 100644 solana/bridge_token_factory/ts/tests/jest.config.cjs create mode 100644 solana/bridge_token_factory/ts/tests/package-lock.json create mode 100644 solana/bridge_token_factory/ts/tests/package.json create mode 100644 solana/bridge_token_factory/ts/tests/src/data/admin/index.ts create mode 100644 solana/bridge_token_factory/ts/tests/src/data/admin/initialize/index.ts create mode 100644 solana/bridge_token_factory/ts/tests/src/data/admin/initialize/simple.ts create mode 100644 solana/bridge_token_factory/ts/tests/src/data/common.ts create mode 100644 solana/bridge_token_factory/ts/tests/src/data/index.ts create mode 100644 solana/bridge_token_factory/ts/tests/src/data/main/index.ts create mode 100644 solana/bridge_token_factory/ts/tests/src/data/user/index.ts create mode 100644 solana/bridge_token_factory/ts/tests/src/data/user/logMetadata/index.ts create mode 100644 solana/bridge_token_factory/ts/tests/src/data/user/logMetadata/mplMetadata.ts create mode 100644 solana/bridge_token_factory/ts/tests/src/data/user/logMetadata/noMetadata.ts create mode 100644 solana/bridge_token_factory/ts/tests/src/jestSetup.ts create mode 100644 solana/bridge_token_factory/ts/tests/src/main.ts create mode 100644 solana/bridge_token_factory/ts/tests/tsconfig.json diff --git a/solana/bridge_token_factory/Anchor.toml b/solana/bridge_token_factory/Anchor.toml index cbf07dd8..d6dd69a9 100644 --- a/solana/bridge_token_factory/Anchor.toml +++ b/solana/bridge_token_factory/Anchor.toml @@ -14,14 +14,3 @@ url = "https://api.apr.dev" cluster = "Localnet" wallet = "~/.config/solana/id.json" -[test] -startup_wait = 20000 -shutdown_wait = 2000 -upgradeable = false - -[[test.genesis]] -address = "worm2ZoG2kUd4vFXhvjh93UUH596ayRfgQ2MgjNMTth" -program = "assets/wormhole.so" - -[scripts] -test = "yarn run ts-mocha -p ./tsconfig.json -t 1000000 tests/**/*.ts" diff --git a/solana/bridge_token_factory/package.json b/solana/bridge_token_factory/package.json index 6d273138..c9adaacb 100644 --- a/solana/bridge_token_factory/package.json +++ b/solana/bridge_token_factory/package.json @@ -1,6 +1,10 @@ { "license": "ISC", "scripts": { + "_test-initialize-simple": "pnpm --filter omni-bridge-solana-tests run test-initialize-simple", + "_test": "pnpm --filter omni-bridge-solana-tests run test", + "test": "anchor test --skip-build", + "pretest": "pnpm --filter omni-bridge-solana-tests run setup-test", "copy-idl": "copyfiles -u 2 target/types/bridge_token_factory.ts ts/sdk/src && copyfiles -u 2 target/idl/bridge_token_factory.json ts/sdk/src", "build-devnet": "PROGRAM_ID=\"3ZtEZ8xABFbUr4c1FVpXbQiVdqv4vwhvfCc8HMmhEeua\" anchor build -- --no-default-features --features devnet", "build-test": "PROGRAM_ID=\"3ZtEZ8xABFbUr4c1FVpXbQiVdqv4vwhvfCc8HMmhEeua\" anchor build -- --no-default-features --features mainnet" diff --git a/solana/bridge_token_factory/pnpm-lock.yaml b/solana/bridge_token_factory/pnpm-lock.yaml index 3a202d75..96cd9b16 100644 --- a/solana/bridge_token_factory/pnpm-lock.yaml +++ b/solana/bridge_token_factory/pnpm-lock.yaml @@ -113,12 +113,107 @@ importers: specifier: ^5.4.10 version: 5.4.10(@types/node@22.8.0) + ts/tests: + dependencies: + '@coral-xyz/anchor': + specifier: ^0.30.1 + version: 0.30.1(bufferutil@4.0.8)(utf-8-validate@5.0.10) + '@metaplex-foundation/mpl-token-metadata': + specifier: ^3.3.0 + version: 3.3.0(@metaplex-foundation/umi@0.9.2) + '@metaplex-foundation/umi': + specifier: ^0.9.2 + version: 0.9.2 + '@metaplex-foundation/umi-bundle-defaults': + specifier: ^0.9.2 + version: 0.9.2(@metaplex-foundation/umi@0.9.2)(@solana/web3.js@1.95.4(bufferutil@4.0.8)(utf-8-validate@5.0.10)) + '@metaplex-foundation/umi-public-keys': + specifier: ^0.8.9 + version: 0.8.9 + '@solana/spl-token': + specifier: ^0.4.9 + version: 0.4.9(@solana/web3.js@1.95.4(bufferutil@4.0.8)(utf-8-validate@5.0.10))(bufferutil@4.0.8)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.6.3)(utf-8-validate@5.0.10) + '@solana/web3.js': + specifier: ^1.95.4 + version: 1.95.4(bufferutil@4.0.8)(utf-8-validate@5.0.10) + bn.js: + specifier: ^5.2.1 + version: 5.2.1 + js-base64: + specifier: ^3.7.7 + version: 3.7.7 + omni-bridge-solana-sdk: + specifier: workspace:* + version: link:../sdk + devDependencies: + '@jest/globals': + specifier: ^29.7.0 + version: 29.7.0 + '@types/bn.js': + specifier: ^5.1.6 + version: 5.1.6 + '@types/jest': + specifier: ^29.5.14 + version: 29.5.14 + '@types/node': + specifier: ^22.7.5 + version: 22.8.0 + gts: + specifier: ^6.0.2 + version: 6.0.2(typescript@5.6.3) + jest: + specifier: ^29.7.0 + version: 29.7.0(@types/node@22.8.0)(ts-node@10.9.2(@types/node@22.8.0)(typescript@5.6.3)) + ts-jest: + specifier: ^29.2.5 + version: 29.2.5(@babel/core@7.26.0)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.26.0))(jest@29.7.0(@types/node@22.8.0)(ts-node@10.9.2(@types/node@22.8.0)(typescript@5.6.3)))(typescript@5.6.3) + ts-node: + specifier: ^10.9.2 + version: 10.9.2(@types/node@22.8.0)(typescript@5.6.3) + typescript: + specifier: ^5.6.3 + version: 5.6.3 + packages: + '@ampproject/remapping@2.3.0': + resolution: {integrity: sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==} + engines: {node: '>=6.0.0'} + '@babel/code-frame@7.26.0': resolution: {integrity: sha512-INCKxTtbXtcNbUZ3YXutwMpEleqttcswhAdee7dhuoVrD2cnuc3PqtERBtxkX5nziX9vnBL8WXmSGwv8CuPV6g==} engines: {node: '>=6.9.0'} + '@babel/compat-data@7.26.2': + resolution: {integrity: sha512-Z0WgzSEa+aUcdiJuCIqgujCshpMWgUpgOxXotrYPSA53hA3qopNaqcJpyr0hVb1FeWdnqFA35/fUtXgBK8srQg==} + engines: {node: '>=6.9.0'} + + '@babel/core@7.26.0': + resolution: {integrity: sha512-i1SLeK+DzNnQ3LL/CswPCa/E5u4lh1k6IAEphON8F+cXt0t9euTshDru0q7/IqMa1PMPz5RnHuHscF8/ZJsStg==} + engines: {node: '>=6.9.0'} + + '@babel/generator@7.26.2': + resolution: {integrity: sha512-zevQbhbau95nkoxSq3f/DC/SC+EEOUZd3DYqfSkMhY2/wfSeaHV1Ew4vk8e+x8lja31IbyuUa2uQ3JONqKbysw==} + engines: {node: '>=6.9.0'} + + '@babel/helper-compilation-targets@7.25.9': + resolution: {integrity: sha512-j9Db8Suy6yV/VHa4qzrj9yZfZxhLWQdVnRlXxmKLYlhWUVB1sB2G5sxuWYXk/whHD9iW76PmNzxZ4UCnTQTVEQ==} + engines: {node: '>=6.9.0'} + + '@babel/helper-module-imports@7.25.9': + resolution: {integrity: sha512-tnUA4RsrmflIM6W6RFTLFSXITtl0wKjgpnLgXyowocVPrbYrLUXSBXDgTs8BlbmIzIdlBySRQjINYs2BAkiLtw==} + engines: {node: '>=6.9.0'} + + '@babel/helper-module-transforms@7.26.0': + resolution: {integrity: sha512-xO+xu6B5K2czEnQye6BHA7DolFFmS3LB7stHZFaOLb1pAwO1HWLS8fXA+eh0A2yIvltPVmx3eNNDBJA2SLHXFw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/helper-plugin-utils@7.25.9': + resolution: {integrity: sha512-kSMlyUVdWe25rEsRGviIgOWnoT/nfABVWlqt9N19/dIPWViAOW2s9wznP5tURbs/IDuNk4gPy3YdYRgH3uxhBw==} + engines: {node: '>=6.9.0'} + '@babel/helper-string-parser@7.25.9': resolution: {integrity: sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==} engines: {node: '>=6.9.0'} @@ -127,19 +222,134 @@ packages: resolution: {integrity: sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==} engines: {node: '>=6.9.0'} + '@babel/helper-validator-option@7.25.9': + resolution: {integrity: sha512-e/zv1co8pp55dNdEcCynfj9X7nyUKUXoUEwfXqaZt0omVOmDe9oOTdKStH4GmAw6zxMFs50ZayuMfHDKlO7Tfw==} + engines: {node: '>=6.9.0'} + + '@babel/helpers@7.26.0': + resolution: {integrity: sha512-tbhNuIxNcVb21pInl3ZSjksLCvgdZy9KwJ8brv993QtIVKJBBkYXz4q4ZbAv31GdnC+R90np23L5FbEBlthAEw==} + engines: {node: '>=6.9.0'} + '@babel/parser@7.26.0': resolution: {integrity: sha512-aP8x5pIw3xvYr/sXT+SEUwyhrXT8rUJRZltK/qN3Db80dcKpTett8cJxHyjk+xYSVXvNnl2SfcJVjbwxpOSscA==} engines: {node: '>=6.0.0'} hasBin: true + '@babel/parser@7.26.2': + resolution: {integrity: sha512-DWMCZH9WA4Maitz2q21SRKHo9QXZxkDsbNZoVD62gusNtNBBqDg9i7uOhASfTfIGNzW+O+r7+jAlM8dwphcJKQ==} + engines: {node: '>=6.0.0'} + hasBin: true + + '@babel/plugin-syntax-async-generators@7.8.4': + resolution: {integrity: sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-bigint@7.8.3': + resolution: {integrity: sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-class-properties@7.12.13': + resolution: {integrity: sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-class-static-block@7.14.5': + resolution: {integrity: sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-import-attributes@7.26.0': + resolution: {integrity: sha512-e2dttdsJ1ZTpi3B9UYGLw41hifAubg19AtCu/2I/F1QNVclOBr1dYpTdmdyZ84Xiz43BS/tCUkMAZNLv12Pi+A==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-import-meta@7.10.4': + resolution: {integrity: sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-json-strings@7.8.3': + resolution: {integrity: sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-jsx@7.25.9': + resolution: {integrity: sha512-ld6oezHQMZsZfp6pWtbjaNDF2tiiCYYDqQszHt5VV437lewP9aSi2Of99CK0D0XB21k7FLgnLcmQKyKzynfeAA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-logical-assignment-operators@7.10.4': + resolution: {integrity: sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-nullish-coalescing-operator@7.8.3': + resolution: {integrity: sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-numeric-separator@7.10.4': + resolution: {integrity: sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-object-rest-spread@7.8.3': + resolution: {integrity: sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-optional-catch-binding@7.8.3': + resolution: {integrity: sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-optional-chaining@7.8.3': + resolution: {integrity: sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-private-property-in-object@7.14.5': + resolution: {integrity: sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-top-level-await@7.14.5': + resolution: {integrity: sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-typescript@7.25.9': + resolution: {integrity: sha512-hjMgRy5hb8uJJjUcdWunWVcoi9bGpJp8p5Ol1229PoN6aytsLwNMgmdftO23wnCLMfVmTwZDWMPNq/D1SY60JQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + '@babel/runtime@7.26.0': resolution: {integrity: sha512-FDSOghenHTiToteC/QRlv2q3DhPZ/oOXTBoirfWNx1Cx3TMVcGWQtMMmQcSvb/JjpNeGzx8Pq/b4fKEJuWm1sw==} engines: {node: '>=6.9.0'} + '@babel/template@7.25.9': + resolution: {integrity: sha512-9DGttpmPvIxBb/2uwpVo3dqJ+O6RooAFOS+lB+xDqoE2PVCE8nfoHMdZLpfCQRLwvohzXISPZcgxt80xLfsuwg==} + engines: {node: '>=6.9.0'} + + '@babel/traverse@7.25.9': + resolution: {integrity: sha512-ZCuvfwOwlz/bawvAuvcj8rrithP2/N55Tzz342AkTvq4qaWbGfmCk/tKhNaV2cthijKrPAA8SRJV5WWe7IBMJw==} + engines: {node: '>=6.9.0'} + '@babel/types@7.26.0': resolution: {integrity: sha512-Z/yiTPj+lDVnF7lWeKCIJzaIkI0vYO87dMpZ4bg4TDrFe4XXLFWL1TbXU27gBP3QccxV9mZICCrnjnYlJjXHOA==} engines: {node: '>=6.9.0'} + '@bcoe/v8-coverage@0.2.3': + resolution: {integrity: sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==} + '@commitlint/parse@19.5.0': resolution: {integrity: sha512-cZ/IxfAlfWYhAQV0TwcbdR1Oc0/r0Ik1GEessDJ3Lbuma/MRO8FRQX76eurcXtmhJC//rj52ZSZuXUg0oIX0Fw==} engines: {node: '>=v18'} @@ -339,13 +549,98 @@ packages: resolution: {integrity: sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==} deprecated: Use @eslint/object-schema instead + '@istanbuljs/load-nyc-config@1.1.0': + resolution: {integrity: sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==} + engines: {node: '>=8'} + + '@istanbuljs/schema@0.1.3': + resolution: {integrity: sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==} + engines: {node: '>=8'} + + '@jest/console@29.7.0': + resolution: {integrity: sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + '@jest/core@29.7.0': + resolution: {integrity: sha512-n7aeXWKMnGtDA48y8TLWJPJmLmmZ642Ceo78cYWEpiD7FzDgmNDV/GCVRorPABdXLJZ/9wzzgZAlHjXjxDHGsg==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + peerDependencies: + node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 + peerDependenciesMeta: + node-notifier: + optional: true + + '@jest/environment@29.7.0': + resolution: {integrity: sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + '@jest/expect-utils@29.7.0': + resolution: {integrity: sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + '@jest/expect@29.7.0': + resolution: {integrity: sha512-8uMeAMycttpva3P1lBHB8VciS9V0XAr3GymPpipdyQXbBcuhkLQOSe8E/p92RyAdToS6ZD1tFkX+CkhoECE0dQ==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + '@jest/fake-timers@29.7.0': + resolution: {integrity: sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + '@jest/globals@29.7.0': + resolution: {integrity: sha512-mpiz3dutLbkW2MNFubUGUEVLkTGiqW6yLVTA+JbP6fI6J5iL9Y0Nlg8k95pcF8ctKwCS7WVxteBs29hhfAotzQ==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + '@jest/reporters@29.7.0': + resolution: {integrity: sha512-DApq0KJbJOEzAFYjHADNNxAE3KbhxQB1y5Kplb5Waqw6zVbuWatSnMjE5gs8FUgEPmNsnZA3NCWl9NG0ia04Pg==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + peerDependencies: + node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 + peerDependenciesMeta: + node-notifier: + optional: true + + '@jest/schemas@29.6.3': + resolution: {integrity: sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + '@jest/source-map@29.6.3': + resolution: {integrity: sha512-MHjT95QuipcPrpLM+8JMSzFx6eHp5Bm+4XeFDJlwsvVBjmKNiIAvasGK2fxz2WbGRlnvqehFbh07MMa7n3YJnw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + '@jest/test-result@29.7.0': + resolution: {integrity: sha512-Fdx+tv6x1zlkJPcWXmMDAG2HBnaR9XPSd5aDWQVsfrZmLVT3lU1cwyxLgRmXR9yrq4NBoEm9BMsfgFzTQAbJYA==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + '@jest/test-sequencer@29.7.0': + resolution: {integrity: sha512-GQwJ5WZVrKnOJuiYiAF52UNUJXgTZx1NHjFSEB0qEMmSZKAkdMoIzw/Cj6x6NF4AvV23AUqDpFzQkN/eYCYTxw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + '@jest/transform@29.7.0': + resolution: {integrity: sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + '@jest/types@29.6.3': + resolution: {integrity: sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + '@jridgewell/gen-mapping@0.3.5': + resolution: {integrity: sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==} + engines: {node: '>=6.0.0'} + '@jridgewell/resolve-uri@3.1.2': resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==} engines: {node: '>=6.0.0'} + '@jridgewell/set-array@1.2.1': + resolution: {integrity: sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==} + engines: {node: '>=6.0.0'} + '@jridgewell/sourcemap-codec@1.5.0': resolution: {integrity: sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==} + '@jridgewell/trace-mapping@0.3.25': + resolution: {integrity: sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==} + '@jridgewell/trace-mapping@0.3.9': resolution: {integrity: sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==} @@ -355,6 +650,92 @@ packages: '@kwsites/promise-deferred@1.1.1': resolution: {integrity: sha512-GaHYm+c0O9MjZRu0ongGBRbinu8gVAMd2UZjji6jVmqKtZluZnptXGWhz1E8j8D2HJ3f/yMxKAUC0b+57wncIw==} + '@metaplex-foundation/mpl-token-metadata@3.3.0': + resolution: {integrity: sha512-t5vO8Wr3ZZZPGrVrGNcosX5FMkwQSgBiVMQMRNDG2De7voYFJmIibD5jdG05EoQ4Y5kZVEiwhYaO+wJB3aO5AA==} + peerDependencies: + '@metaplex-foundation/umi': '>= 0.8.2 < 1' + + '@metaplex-foundation/mpl-toolbox@0.9.4': + resolution: {integrity: sha512-fd6JxfoLbj/MM8FG2x91KYVy1U6AjBQw4qjt7+Da3trzQaWnSaYHDcYRG/53xqfvZ9qofY1T2t53GXPlD87lnQ==} + peerDependencies: + '@metaplex-foundation/umi': '>= 0.8.2 < 1' + + '@metaplex-foundation/umi-bundle-defaults@0.9.2': + resolution: {integrity: sha512-kV3tfvgvRjVP1p9OFOtH+ibOtN9omVJSwKr0We4/9r45e5LTj+32su0V/rixZUkG1EZzzOYBsxhtIE0kIw/Hrw==} + peerDependencies: + '@metaplex-foundation/umi': ^0.9.2 + '@solana/web3.js': ^1.72.0 + + '@metaplex-foundation/umi-downloader-http@0.9.2': + resolution: {integrity: sha512-tzPT9hBwenzTzAQg07rmsrqZfgguAXELbcJrsYMoASp5VqWFXYIP00g94KET6XLjWUXH4P1J2zoa6hGennPXHA==} + peerDependencies: + '@metaplex-foundation/umi': ^0.9.2 + + '@metaplex-foundation/umi-eddsa-web3js@0.9.2': + resolution: {integrity: sha512-hhPCxXbYIp4BC4z9gK78sXpWLkNSrfv4ndhF5ruAkdIp7GcRVYKj0QnOUO6lGYGiIkNlw20yoTwOe1CT//OfTQ==} + peerDependencies: + '@metaplex-foundation/umi': ^0.9.2 + '@solana/web3.js': ^1.72.0 + + '@metaplex-foundation/umi-http-fetch@0.9.2': + resolution: {integrity: sha512-YCZuBu24T9ZzEDe4+w12LEZm/fO9pkyViZufGgASC5NX93814Lvf6Ssjn/hZzjfA7CvZbvLFbmujc6CV3Q/m9Q==} + peerDependencies: + '@metaplex-foundation/umi': ^0.9.2 + + '@metaplex-foundation/umi-options@0.8.9': + resolution: {integrity: sha512-jSQ61sZMPSAk/TXn8v8fPqtz3x8d0/blVZXLLbpVbo2/T5XobiI6/MfmlUosAjAUaQl6bHRF8aIIqZEFkJiy4A==} + + '@metaplex-foundation/umi-program-repository@0.9.2': + resolution: {integrity: sha512-g3+FPqXEmYsBa8eETtUE2gb2Oe3mqac0z3/Ur1TvAg5TtIy3mzRzOy/nza+sgzejnfcxcVg835rmpBaxpBnjDA==} + peerDependencies: + '@metaplex-foundation/umi': ^0.9.2 + + '@metaplex-foundation/umi-public-keys@0.8.9': + resolution: {integrity: sha512-CxMzN7dgVGOq9OcNCJe2casKUpJ3RmTVoOvDFyeoTQuK+vkZ1YSSahbqC1iGuHEtKTLSjtWjKvUU6O7zWFTw3Q==} + + '@metaplex-foundation/umi-rpc-chunk-get-accounts@0.9.2': + resolution: {integrity: sha512-YRwVf6xH0jPBAUgMhEPi+UbjioAeqTXmjsN2TnmQCPAmHbrHrMRj0rlWYwFLWAgkmoxazYrXP9lqOFRrfOGAEA==} + peerDependencies: + '@metaplex-foundation/umi': ^0.9.2 + + '@metaplex-foundation/umi-rpc-web3js@0.9.2': + resolution: {integrity: sha512-MqcsBz8B4wGl6jxsf2Jo/rAEpYReU9VCSR15QSjhvADHMmdFxCIZCCAgE+gDE2Vuanfl437VhOcP3g5Uw8C16Q==} + peerDependencies: + '@metaplex-foundation/umi': ^0.9.2 + '@solana/web3.js': ^1.72.0 + + '@metaplex-foundation/umi-serializer-data-view@0.9.2': + resolution: {integrity: sha512-5vGptadJxUxvUcyrwFZxXlEc6Q7AYySBesizCtrBFUY8w8PnF2vzmS45CP1MLySEATNH6T9mD4Rs0tLb87iQyA==} + peerDependencies: + '@metaplex-foundation/umi': ^0.9.2 + + '@metaplex-foundation/umi-serializers-core@0.8.9': + resolution: {integrity: sha512-WT82tkiYJ0Qmscp7uTj1Hz6aWQPETwaKLAENAUN5DeWghkuBKtuxyBKVvEOuoXerJSdhiAk0e8DWA4cxcTTQ/w==} + + '@metaplex-foundation/umi-serializers-encodings@0.8.9': + resolution: {integrity: sha512-N3VWLDTJ0bzzMKcJDL08U3FaqRmwlN79FyE4BHj6bbAaJ9LEHjDQ9RJijZyWqTm0jE7I750fU7Ow5EZL38Xi6Q==} + + '@metaplex-foundation/umi-serializers-numbers@0.8.9': + resolution: {integrity: sha512-NtBf1fnVNQJHFQjLFzRu2i9GGnigb9hOm/Gfrk628d0q0tRJB7BOM3bs5C61VAs7kJs4yd+pDNVAERJkknQ7Lg==} + + '@metaplex-foundation/umi-serializers@0.9.0': + resolution: {integrity: sha512-hAOW9Djl4w4ioKeR4erDZl5IG4iJdP0xA19ZomdaCbMhYAAmG/FEs5khh0uT2mq53/MnzWcXSUPoO8WBN4Q+Vg==} + + '@metaplex-foundation/umi-transaction-factory-web3js@0.9.2': + resolution: {integrity: sha512-fR1Kf21uylMFd1Smkltmj4jTNxhqSWf416owsJ+T+cvJi2VCOcOwq/3UFzOrpz78fA0RhsajKYKj0HYsRnQI1g==} + peerDependencies: + '@metaplex-foundation/umi': ^0.9.2 + '@solana/web3.js': ^1.72.0 + + '@metaplex-foundation/umi-web3js-adapters@0.9.2': + resolution: {integrity: sha512-RQqUTtHYY9fmEMnq7s3Hiv/81flGaoI0ZVVoafnFVaQLnxU6QBKxtboRZHk43XtD9CiFh5f9izrMJX7iK7KlOA==} + peerDependencies: + '@metaplex-foundation/umi': ^0.9.2 + '@solana/web3.js': ^1.72.0 + + '@metaplex-foundation/umi@0.9.2': + resolution: {integrity: sha512-9i4Acm4pruQfJcpRrc2EauPBwkfDN0I9QTvJyZocIlKgoZwD6A6wH0PViH1AjOVG5CQCd1YI3tJd5XjYE1ElBw==} + '@microsoft/api-extractor-model@7.29.4': resolution: {integrity: sha512-LHOMxmT8/tU1IiiiHOdHFF83Qsi+V8d0kLfscG4EvQE9cafiR8blOYr8SfkQKWB1wgEilQgXJX3MIA4vetDLZw==} @@ -518,6 +899,15 @@ packages: '@shikijs/vscode-textmate@9.3.0': resolution: {integrity: sha512-jn7/7ky30idSkd/O5yDBfAnVt+JJpepofP/POZ1iMOxK59cOfqIgg/Dj0eFsjOTMw+4ycJN0uhZH/Eb0bs/EUA==} + '@sinclair/typebox@0.27.8': + resolution: {integrity: sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==} + + '@sinonjs/commons@3.0.1': + resolution: {integrity: sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==} + + '@sinonjs/fake-timers@10.3.0': + resolution: {integrity: sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==} + '@solana/buffer-layout-utils@0.2.0': resolution: {integrity: sha512-szG4sxgJGktbuZYDg2FfNmkMi0DYQoVjN2h7ta1W1hPrwzarcFLBq9UpX1UjNXsNpT9dn+chgprtWGioUAr4/g==} engines: {node: '>= 10'} @@ -613,6 +1003,18 @@ packages: '@types/argparse@1.0.38': resolution: {integrity: sha512-ebDJ9b0e702Yr7pWgB0jzm+CX4Srzz8RcXtLJDJB+BSccqMa36uyH/zUsSYao5+BD1ytv3k3rPYCq4mAE1hsXA==} + '@types/babel__core@7.20.5': + resolution: {integrity: sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==} + + '@types/babel__generator@7.6.8': + resolution: {integrity: sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw==} + + '@types/babel__template@7.4.4': + resolution: {integrity: sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==} + + '@types/babel__traverse@7.20.6': + resolution: {integrity: sha512-r1bzfrm0tomOI8g1SzvCaQHo6Lcv6zu0EA+W2kHrt8dyrHQxGzBBL4kdkzIS+jBMV+EYcMAEAqXqYaLJq5rOZg==} + '@types/bn.js@5.1.6': resolution: {integrity: sha512-Xh8vSwUeMKeYYrj3cX4lGQgFSF/N03r+tv4AiLl1SucqV+uTQpxRcnM8AkXKHwYP9ZPXOYXRr2KPXpVlIvqh9w==} @@ -628,9 +1030,24 @@ packages: '@types/expand-tilde@2.0.2': resolution: {integrity: sha512-wlsMYiapmIR4Eq/Z0qysN8xaDMjSkO6AIDNFx9oxgWGeKVA1jU+NzwPRZErBNP5z6/dx6QNkNpKglBGPO9OkTA==} + '@types/graceful-fs@4.1.9': + resolution: {integrity: sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ==} + '@types/hast@3.0.4': resolution: {integrity: sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==} + '@types/istanbul-lib-coverage@2.0.6': + resolution: {integrity: sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==} + + '@types/istanbul-lib-report@3.0.3': + resolution: {integrity: sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA==} + + '@types/istanbul-reports@3.0.4': + resolution: {integrity: sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==} + + '@types/jest@29.5.14': + resolution: {integrity: sha512-ZN+4sdnLUbo8EVvVc2ao0GFW6oVrQRPn4K2lglySj7APvSrgzxHiNNK99us4WDMi57xxA2yggblIAMNhXOotLQ==} + '@types/json-schema@7.0.15': resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} @@ -655,6 +1072,9 @@ packages: '@types/semver@7.5.8': resolution: {integrity: sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==} + '@types/stack-utils@2.0.3': + resolution: {integrity: sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==} + '@types/unist@3.0.3': resolution: {integrity: sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==} @@ -667,6 +1087,12 @@ packages: '@types/ws@8.5.12': resolution: {integrity: sha512-3tPRkv1EtkDpzlgyKyI8pGsGZAGPEaXeu0DOj5DI25Ja91bdAYddYHbADRYVrZMRbfW+1l5YwXVDKohDJNQxkQ==} + '@types/yargs-parser@21.0.3': + resolution: {integrity: sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==} + + '@types/yargs@17.0.33': + resolution: {integrity: sha512-WpxBCKWPLr4xSsHgz511rFJAM+wS28w2zEO1QDNY5zM/S8ok70NNfztH0xwhqKyaK0OHCbN98LDAZuy1ctxDkA==} + '@typescript-eslint/eslint-plugin@5.62.0': resolution: {integrity: sha512-TiZzBSJja/LbhNPvk6yc0JrX9XqhQ0hdh6M2svYfsHGejaKFIAGd9MQ+ERIMzLGlN/kZoYIgdxFV0PuljTKXag==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -873,9 +1299,17 @@ packages: resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} engines: {node: '>=8'} + ansi-styles@5.2.0: + resolution: {integrity: sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==} + engines: {node: '>=10'} + any-promise@1.3.0: resolution: {integrity: sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==} + anymatch@3.1.3: + resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} + engines: {node: '>= 8'} + arg@4.1.3: resolution: {integrity: sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==} @@ -904,9 +1338,37 @@ packages: resolution: {integrity: sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA==} engines: {node: '>=0.10.0'} + async@3.2.6: + resolution: {integrity: sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==} + + babel-jest@29.7.0: + resolution: {integrity: sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + peerDependencies: + '@babel/core': ^7.8.0 + babel-plugin-add-module-exports@0.2.1: resolution: {integrity: sha512-3AN/9V/rKuv90NG65m4tTHsI04XrCKsWbztIcW7a8H5iIN7WlvWucRtVV0V/rT4QvtA11n5Vmp20fLwfMWqp6g==} + babel-plugin-istanbul@6.1.1: + resolution: {integrity: sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==} + engines: {node: '>=8'} + + babel-plugin-jest-hoist@29.6.3: + resolution: {integrity: sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + babel-preset-current-node-syntax@1.1.0: + resolution: {integrity: sha512-ldYss8SbBlWva1bs28q78Ju5Zq1F+8BrqBZZ0VFhLBvhh6lCpC2o3gDJi/5DRLs9FgYZCnmPYIVFU4lRXCkyUw==} + peerDependencies: + '@babel/core': ^7.0.0 + + babel-preset-jest@29.6.3: + resolution: {integrity: sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + peerDependencies: + '@babel/core': ^7.0.0 + balanced-match@1.0.2: resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} @@ -942,9 +1404,24 @@ packages: resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} engines: {node: '>=8'} + browserslist@4.24.2: + resolution: {integrity: sha512-ZIc+Q62revdMcqC6aChtW4jz3My3klmCO1fEmINZY/8J3EpBg5/A/D0AKmBveUh6pgoeycoMkVMko84tuYS+Gg==} + engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} + hasBin: true + + bs-logger@0.2.6: + resolution: {integrity: sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog==} + engines: {node: '>= 6'} + bs58@4.0.1: resolution: {integrity: sha512-Ok3Wdf5vOIlBrgCvTq96gBkJw+JUEzdBgyaza5HLtPm7yTHkjRy8+JzNyHF7BHa0bNWOQIp3m5YF0nnFcOIKLw==} + bser@2.1.1: + resolution: {integrity: sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==} + + buffer-from@1.1.2: + resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} + buffer-layout@1.2.2: resolution: {integrity: sha512-kWSuLN694+KTk8SrYvCqwP2WcgQjoRCiF5b4QDvkkz8EmgD+aWAIceGFKMIAdmF/pH+vpgNV3d3kAKorcdAmWA==} engines: {node: '>=4.5'} @@ -975,6 +1452,9 @@ packages: resolution: {integrity: sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==} engines: {node: '>=10'} + caniuse-lite@1.0.30001683: + resolution: {integrity: sha512-iqmNnThZ0n70mNwvxpEC2nBJ037ZHZUoBI5Gorh1Mw6IlEAZujEoU1tXA628iZfzm7R9FvFzxbfdgml82a3k8Q==} + ccount@2.0.1: resolution: {integrity: sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==} @@ -986,6 +1466,10 @@ packages: resolution: {integrity: sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==} engines: {node: ^12.17.0 || ^14.13 || >=16.0.0} + char-regex@1.0.2: + resolution: {integrity: sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==} + engines: {node: '>=10'} + character-entities-html4@2.1.0: resolution: {integrity: sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA==} @@ -995,6 +1479,13 @@ packages: chardet@0.7.0: resolution: {integrity: sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==} + ci-info@3.9.0: + resolution: {integrity: sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==} + engines: {node: '>=8'} + + cjs-module-lexer@1.4.1: + resolution: {integrity: sha512-cuSVIHi9/9E/+821Qjdvngor+xpnlwnuwIyZOaLmHBVdXL+gP+I6QQB9VkO7RI77YIcTV+S1W9AreJ5eN63JBA==} + cli-cursor@3.1.0: resolution: {integrity: sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==} engines: {node: '>=8'} @@ -1006,6 +1497,17 @@ packages: cliui@7.0.4: resolution: {integrity: sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==} + cliui@8.0.1: + resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==} + engines: {node: '>=12'} + + co@4.6.0: + resolution: {integrity: sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==} + engines: {iojs: '>= 1.0.0', node: '>= 0.12.0'} + + collect-v8-coverage@1.0.2: + resolution: {integrity: sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q==} + color-convert@2.0.1: resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} engines: {node: '>=7.0.0'} @@ -1047,6 +1549,9 @@ packages: engines: {node: '>=16'} hasBin: true + convert-source-map@2.0.0: + resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} + copyfiles@2.4.1: resolution: {integrity: sha512-fereAvAvxDrQDOXybk3Qu3dPbOoKoysFMWtkY3mv5BsL8//OSZVL5DCLYqgRfY5cWirgRzlC+WSrxp6Bo3eNZg==} hasBin: true @@ -1054,6 +1559,11 @@ packages: core-util-is@1.0.3: resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==} + create-jest@29.7.0: + resolution: {integrity: sha512-Adz2bdH0Vq3F53KEMJOoftQFutWCukm6J24wbPWRO4k1kMY7gS7ds/uoJkNuV8wDCtWWnuwGcJwpWcih+zEW1Q==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + hasBin: true + create-require@1.1.1: resolution: {integrity: sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==} @@ -1102,9 +1612,21 @@ packages: resolution: {integrity: sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==} engines: {node: '>=0.10.0'} + dedent@1.5.3: + resolution: {integrity: sha512-NHQtfOOW68WD8lgypbLA5oT+Bt0xXJhiYvoR6SmmNXZfpzOGXwdKWmcwG8N7PwVVWV3eF/68nmD9BaJSsTBhyQ==} + peerDependencies: + babel-plugin-macros: ^3.1.0 + peerDependenciesMeta: + babel-plugin-macros: + optional: true + deep-is@0.1.4: resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} + deepmerge@4.3.1: + resolution: {integrity: sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==} + engines: {node: '>=0.10.0'} + delay@5.0.0: resolution: {integrity: sha512-ReEBKkIfe4ya47wlPYf/gu5ib6yUG0/Aez0JQZQz94kiWtRQvZIQbTiehsnwHvLSWJnQdhVeqYue7Id1dKr0qw==} engines: {node: '>=10'} @@ -1117,9 +1639,17 @@ packages: resolution: {integrity: sha512-DtCOLG98P007x7wiiOmfI0fi3eIKyWiLTGJ2MDnVi/E04lWGbf+JzrRHMm0rgIIZJGtHpKpbVgLWHrv8xXpc3Q==} engines: {node: '>=0.10.0'} + detect-newline@3.1.0: + resolution: {integrity: sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==} + engines: {node: '>=8'} + devlop@1.1.0: resolution: {integrity: sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==} + diff-sequences@29.6.3: + resolution: {integrity: sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + diff@4.0.2: resolution: {integrity: sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==} engines: {node: '>=0.3.1'} @@ -1139,6 +1669,18 @@ packages: resolution: {integrity: sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==} engines: {node: '>=8'} + ejs@3.1.10: + resolution: {integrity: sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA==} + engines: {node: '>=0.10.0'} + hasBin: true + + electron-to-chromium@1.5.64: + resolution: {integrity: sha512-IXEuxU+5ClW2IGEYFC2T7szbyVgehupCWQe5GNh+H065CD6U6IFN0s4KeAMFGNmQolRU4IV7zGBWSYMmZ8uuqQ==} + + emittery@0.13.1: + resolution: {integrity: sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==} + engines: {node: '>=12'} + emoji-regex@8.0.0: resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} @@ -1177,6 +1719,10 @@ packages: resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==} engines: {node: '>=0.8.0'} + escape-string-regexp@2.0.0: + resolution: {integrity: sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==} + engines: {node: '>=8'} + escape-string-regexp@4.0.0: resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} engines: {node: '>=10'} @@ -1288,6 +1834,11 @@ packages: resolution: {integrity: sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + esprima@4.0.1: + resolution: {integrity: sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==} + engines: {node: '>=4'} + hasBin: true + esquery@1.6.0: resolution: {integrity: sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==} engines: {node: '>=0.10'} @@ -1325,10 +1876,18 @@ packages: resolution: {integrity: sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==} engines: {node: '>=10'} + exit@0.1.2: + resolution: {integrity: sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==} + engines: {node: '>= 0.8.0'} + expand-tilde@2.0.2: resolution: {integrity: sha512-A5EmesHW6rfnZ9ysHQjPdJRni0SRar0tjtG5MNtm9n5TUvsYU8oozprtRD4AqHxcZWWlVuAmQo2nWKfN9oyjTw==} engines: {node: '>=0.10.0'} + expect@29.7.0: + resolution: {integrity: sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + extend@3.0.2: resolution: {integrity: sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==} @@ -1365,6 +1924,9 @@ packages: fastq@1.17.1: resolution: {integrity: sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==} + fb-watchman@2.0.2: + resolution: {integrity: sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==} + figures@3.2.0: resolution: {integrity: sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==} engines: {node: '>=8'} @@ -1376,6 +1938,9 @@ packages: file-uri-to-path@1.0.0: resolution: {integrity: sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==} + filelist@1.0.4: + resolution: {integrity: sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==} + fill-range@7.1.1: resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} engines: {node: '>=8'} @@ -1430,10 +1995,18 @@ packages: function-bind@1.1.2: resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} + gensync@1.0.0-beta.2: + resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} + engines: {node: '>=6.9.0'} + get-caller-file@2.0.5: resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} engines: {node: 6.* || 8.* || >= 10.*} + get-package-type@0.1.0: + resolution: {integrity: sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==} + engines: {node: '>=8.0.0'} + get-stream@3.0.0: resolution: {integrity: sha512-GlhdIUuVakc8SJ6kK0zAFbiGzRFzNnY4jUuEbV9UROo4Y+0Ny4fjvcZFVTeDA4odpFyOQzaw6hXukJSq/f28sQ==} engines: {node: '>=4'} @@ -1465,6 +2038,10 @@ packages: resolution: {integrity: sha512-5lsx1NUDHtSjfg0eHlmYvZKv8/nVqX4ckFbM+FrGcQ+04KWcWFo9P5MxPZYSzUvyzmdTbI7Eix8Q4IbELDqzKg==} engines: {node: '>=0.10.0'} + globals@11.12.0: + resolution: {integrity: sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==} + engines: {node: '>=4'} + globals@13.24.0: resolution: {integrity: sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==} engines: {node: '>=8'} @@ -1526,6 +2103,9 @@ packages: resolution: {integrity: sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==} engines: {node: '>=10'} + html-escaper@2.0.2: + resolution: {integrity: sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==} + html-void-elements@3.0.0: resolution: {integrity: sha512-bEqo66MRXsUGxWHV5IP0PUiAWwoEjba4VCzg0LjFJBpchPaTfyfCKTG6bc5F8ucKec3q5y6qOdGyYTSBEvhCrg==} @@ -1555,6 +2135,11 @@ packages: resolution: {integrity: sha512-rKtvo6a868b5Hu3heneU+L4yEQ4jYKLtjpnPeUdK7h0yzXGmyBTypknlkCvHFBqfX9YlorEiMM6Dnq/5atfHkw==} engines: {node: '>=8'} + import-local@3.2.0: + resolution: {integrity: sha512-2SPlun1JUPWoM6t3F0dw0FkCF/jWY8kttcY4f599GLTSjh2OCuuhdTkJQsEcZzBqbXZGKMK2OqW1oZsjtf/gQA==} + engines: {node: '>=8'} + hasBin: true + imurmurhash@0.1.4: resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} engines: {node: '>=0.8.19'} @@ -1600,6 +2185,10 @@ packages: resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} engines: {node: '>=8'} + is-generator-fn@2.1.0: + resolution: {integrity: sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==} + engines: {node: '>=6'} + is-git-repository@1.1.1: resolution: {integrity: sha512-hxLpJytJnIZ5Og5QsxSkzmb8Qx8rGau9bio1JN/QtXcGEFuSsQYau0IiqlsCwftsfVYjF1mOq6uLdmwNSspgpA==} @@ -1669,21 +2258,191 @@ packages: peerDependencies: ws: '*' - jayson@4.1.2: - resolution: {integrity: sha512-5nzMWDHy6f+koZOuYsArh2AXs73NfWYVlFyJJuCedr93GpY+Ku8qq10ropSXVfHK+H0T6paA88ww+/dV+1fBNA==} + istanbul-lib-coverage@3.2.2: + resolution: {integrity: sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==} engines: {node: '>=8'} - hasBin: true - jju@1.4.0: - resolution: {integrity: sha512-8wb9Yw966OSxApiCt0K3yNJL8pnNeIv+OEq2YMidz4FKP6nonSRoOXc80iXY4JaN2FC11B9qsNmDsm+ZOfMROA==} + istanbul-lib-instrument@5.2.1: + resolution: {integrity: sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==} + engines: {node: '>=8'} - js-tokens@4.0.0: - resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} + istanbul-lib-instrument@6.0.3: + resolution: {integrity: sha512-Vtgk7L/R2JHyyGW07spoFlB8/lpjiOLTjMdms6AFMraYt3BaJauod/NGrfnVG/y4Ix1JEuMRPDPEj2ua+zz1/Q==} + engines: {node: '>=10'} + + istanbul-lib-report@3.0.1: + resolution: {integrity: sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==} + engines: {node: '>=10'} + + istanbul-lib-source-maps@4.0.1: + resolution: {integrity: sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==} + engines: {node: '>=10'} + + istanbul-reports@3.1.7: + resolution: {integrity: sha512-BewmUXImeuRk2YY0PVbxgKAysvhRPUQE0h5QRM++nVWyubKGV0l8qQ5op8+B2DOmwSe63Jivj0BjkPQVf8fP5g==} + engines: {node: '>=8'} + + jake@10.9.2: + resolution: {integrity: sha512-2P4SQ0HrLQ+fw6llpLnOaGAvN2Zu6778SJMrCUwns4fOoG9ayrTiZk3VV8sCPkVZF8ab0zksVpS8FDY5pRCNBA==} + engines: {node: '>=10'} + hasBin: true + + jayson@4.1.2: + resolution: {integrity: sha512-5nzMWDHy6f+koZOuYsArh2AXs73NfWYVlFyJJuCedr93GpY+Ku8qq10ropSXVfHK+H0T6paA88ww+/dV+1fBNA==} + engines: {node: '>=8'} + hasBin: true + + jest-changed-files@29.7.0: + resolution: {integrity: sha512-fEArFiwf1BpQ+4bXSprcDc3/x4HSzL4al2tozwVpDFpsxALjLYdyiIK4e5Vz66GQJIbXJ82+35PtysofptNX2w==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + jest-circus@29.7.0: + resolution: {integrity: sha512-3E1nCMgipcTkCocFwM90XXQab9bS+GMsjdpmPrlelaxwD93Ad8iVEjX/vvHPdLPnFf+L40u+5+iutRdA1N9myw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + jest-cli@29.7.0: + resolution: {integrity: sha512-OVVobw2IubN/GSYsxETi+gOe7Ka59EFMR/twOU3Jb2GnKKeMGJB5SGUUrEz3SFVmJASUdZUzy83sLNNQ2gZslg==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + hasBin: true + peerDependencies: + node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 + peerDependenciesMeta: + node-notifier: + optional: true + + jest-config@29.7.0: + resolution: {integrity: sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + peerDependencies: + '@types/node': '*' + ts-node: '>=9.0.0' + peerDependenciesMeta: + '@types/node': + optional: true + ts-node: + optional: true + + jest-diff@29.7.0: + resolution: {integrity: sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + jest-docblock@29.7.0: + resolution: {integrity: sha512-q617Auw3A612guyaFgsbFeYpNP5t2aoUNLwBUbc/0kD1R4t9ixDbyFTHd1nok4epoVFpr7PmeWHrhvuV3XaJ4g==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + jest-each@29.7.0: + resolution: {integrity: sha512-gns+Er14+ZrEoC5fhOfYCY1LOHHr0TI+rQUHZS8Ttw2l7gl+80eHc/gFf2Ktkw0+SIACDTeWvpFcv3B04VembQ==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + jest-environment-node@29.7.0: + resolution: {integrity: sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + jest-get-type@29.6.3: + resolution: {integrity: sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + jest-haste-map@29.7.0: + resolution: {integrity: sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + jest-leak-detector@29.7.0: + resolution: {integrity: sha512-kYA8IJcSYtST2BY9I+SMC32nDpBT3J2NvWJx8+JCuCdl/CR1I4EKUJROiP8XtCcxqgTTBGJNdbB1A8XRKbTetw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + jest-matcher-utils@29.7.0: + resolution: {integrity: sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + jest-message-util@29.7.0: + resolution: {integrity: sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + jest-mock@29.7.0: + resolution: {integrity: sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + jest-pnp-resolver@1.2.3: + resolution: {integrity: sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==} + engines: {node: '>=6'} + peerDependencies: + jest-resolve: '*' + peerDependenciesMeta: + jest-resolve: + optional: true + + jest-regex-util@29.6.3: + resolution: {integrity: sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + jest-resolve-dependencies@29.7.0: + resolution: {integrity: sha512-un0zD/6qxJ+S0et7WxeI3H5XSe9lTBBR7bOHCHXkKR6luG5mwDDlIzVQ0V5cZCuoTgEdcdwzTghYkTWfubi+nA==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + jest-resolve@29.7.0: + resolution: {integrity: sha512-IOVhZSrg+UvVAshDSDtHyFCCBUl/Q3AAJv8iZ6ZjnZ74xzvwuzLXid9IIIPgTnY62SJjfuupMKZsZQRsCvxEgA==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + jest-runner@29.7.0: + resolution: {integrity: sha512-fsc4N6cPCAahybGBfTRcq5wFR6fpLznMg47sY5aDpsoejOcVYFb07AHuSnR0liMcPTgBsA3ZJL6kFOjPdoNipQ==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + jest-runtime@29.7.0: + resolution: {integrity: sha512-gUnLjgwdGqW7B4LvOIkbKs9WGbn+QLqRQQ9juC6HndeDiezIwhDP+mhMwHWCEcfQ5RUXa6OPnFF8BJh5xegwwQ==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + jest-snapshot@29.7.0: + resolution: {integrity: sha512-Rm0BMWtxBcioHr1/OX5YCP8Uov4riHvKPknOGs804Zg9JGZgmIBkbtlxJC/7Z4msKYVbIJtfU+tKb8xlYNfdkw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + jest-util@29.7.0: + resolution: {integrity: sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + jest-validate@29.7.0: + resolution: {integrity: sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + jest-watcher@29.7.0: + resolution: {integrity: sha512-49Fg7WXkU3Vl2h6LbLtMQ/HyB6rXSIX7SqvBLQmssRBGN9I0PNvPmAmCWSOY6SOvrjhI/F7/bGAv9RtnsPA03g==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + jest-worker@29.7.0: + resolution: {integrity: sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + jest@29.7.0: + resolution: {integrity: sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + hasBin: true + peerDependencies: + node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 + peerDependenciesMeta: + node-notifier: + optional: true + + jju@1.4.0: + resolution: {integrity: sha512-8wb9Yw966OSxApiCt0K3yNJL8pnNeIv+OEq2YMidz4FKP6nonSRoOXc80iXY4JaN2FC11B9qsNmDsm+ZOfMROA==} + + js-base64@3.7.7: + resolution: {integrity: sha512-7rCnleh0z2CkXhH67J8K1Ytz0b2Y+yxTPL+/KOJoa20hfnVQ/3/T6W/KflYI4bRHRagNeXeU2bkNGI3v1oS/lw==} + + js-tokens@4.0.0: + resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} + + js-yaml@3.14.1: + resolution: {integrity: sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==} + hasBin: true js-yaml@4.1.0: resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} hasBin: true + jsesc@3.0.2: + resolution: {integrity: sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g==} + engines: {node: '>=6'} + hasBin: true + json-buffer@3.0.1: resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==} @@ -1724,9 +2483,17 @@ packages: resolution: {integrity: sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==} engines: {node: '>=0.10.0'} + kleur@3.0.3: + resolution: {integrity: sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==} + engines: {node: '>=6'} + kolorist@1.8.0: resolution: {integrity: sha512-Y+60/zizpJ3HRH8DCss+q95yr6145JXZo46OTpFvDZWLfRCE4qChOyk1b26nMaNpfHHgxagk9dXT5OP0Tfe+dQ==} + leven@3.1.0: + resolution: {integrity: sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==} + engines: {node: '>=6'} + levn@0.4.1: resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} engines: {node: '>= 0.8.0'} @@ -1753,6 +2520,9 @@ packages: resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} engines: {node: '>=10'} + lodash.memoize@4.1.2: + resolution: {integrity: sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==} + lodash.merge@4.6.2: resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} @@ -1765,6 +2535,9 @@ packages: lru-cache@4.1.5: resolution: {integrity: sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==} + lru-cache@5.1.1: + resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} + lru-cache@6.0.0: resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==} engines: {node: '>=10'} @@ -1775,9 +2548,16 @@ packages: magic-string@0.30.12: resolution: {integrity: sha512-Ea8I3sQMVXr8JhN4z+H/d8zwo+tYDgHE9+5G4Wnrwhs0gaK9fXTKx0Tw5Xwsd/bCPTTZNRAdpyzvoeORe9LYpw==} + make-dir@4.0.0: + resolution: {integrity: sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==} + engines: {node: '>=10'} + make-error@1.3.6: resolution: {integrity: sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==} + makeerror@1.0.12: + resolution: {integrity: sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==} + map-cache@0.2.2: resolution: {integrity: sha512-8y/eV9QQZCiyn1SprXSrCmqJN0yNRATe+PO8ztwqrvrbdRLA3eYJF0yaR0YayLWkMbsQSKWS9N2gPcGEc4UsZg==} engines: {node: '>=0.10.0'} @@ -1848,6 +2628,10 @@ packages: minimatch@3.1.2: resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} + minimatch@5.1.6: + resolution: {integrity: sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==} + engines: {node: '>=10'} + minimatch@9.0.5: resolution: {integrity: sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==} engines: {node: '>=16 || 14 >=14.17'} @@ -1910,6 +2694,12 @@ packages: resolution: {integrity: sha512-IRUxE4BVsHWXkV/SFOut4qTlagw2aM8T5/vnTsmrHJvVoKueJHRc/JaFND7QDDc61kLYUJ6qlZM3sqTSyx2dTw==} hasBin: true + node-int64@0.4.0: + resolution: {integrity: sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==} + + node-releases@2.0.18: + resolution: {integrity: sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g==} + noms@0.0.0: resolution: {integrity: sha512-lNDU9VJaOPxUmXcLb+HQFeUgQQPtMI24Gt6hgfuMHRJgMRHMF/qZ4HJD3GDru4sSw9IQl2jPjAYnQrdIeLbwow==} @@ -1920,6 +2710,10 @@ packages: resolution: {integrity: sha512-p2W1sgqij3zMMyRC067Dg16bfzVH+w7hyegmpIvZ4JNjqtGOVAIvLmjBx3yP7YTe9vKJgkoNOPjwQGogDoMXFA==} engines: {node: '>=10'} + normalize-path@3.0.0: + resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} + engines: {node: '>=0.10.0'} + npm-run-path@2.0.2: resolution: {integrity: sha512-lJxZYlT4DW/bRUtFh1MQIWqmLwQfAxnqWG4HhEdjMlkrJYnJn0Jrr2u3mgxqaWsdiBc76TYkTG/mhrnYTuzfHw==} engines: {node: '>=4'} @@ -2049,6 +2843,14 @@ packages: resolution: {integrity: sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==} engines: {node: '>=12'} + pirates@4.0.6: + resolution: {integrity: sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==} + engines: {node: '>= 6'} + + pkg-dir@4.2.0: + resolution: {integrity: sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==} + engines: {node: '>=8'} + pkg-types@1.2.1: resolution: {integrity: sha512-sQoqa8alT3nHjGuTjuKgOnvjo4cljkufdtLMnO2LBP/wRwuDlo1tkaEdMxCRhyGRPacv/ztlZgDPm2b7FAmEvw==} @@ -2074,9 +2876,17 @@ packages: engines: {node: '>=14'} hasBin: true + pretty-format@29.7.0: + resolution: {integrity: sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + process-nextick-args@2.0.1: resolution: {integrity: sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==} + prompts@2.4.2: + resolution: {integrity: sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==} + engines: {node: '>= 6'} + property-information@6.5.0: resolution: {integrity: sha512-PgTgs/BlvHxOu8QuEN7wi5A0OmXaBcHpmCSTehcs6Uuu9IkDIEo13Hy7n898RHfrQ49vKCoGeWZSaAK01nwVig==} @@ -2091,6 +2901,9 @@ packages: resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} engines: {node: '>=6'} + pure-rand@6.1.0: + resolution: {integrity: sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA==} + queue-microtask@1.2.3: resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} @@ -2098,6 +2911,9 @@ packages: resolution: {integrity: sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g==} engines: {node: '>=8'} + react-is@18.3.1: + resolution: {integrity: sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==} + read-pkg-up@7.0.1: resolution: {integrity: sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==} engines: {node: '>=8'} @@ -2138,6 +2954,10 @@ packages: resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==} engines: {node: '>=0.10.0'} + resolve-cwd@3.0.0: + resolution: {integrity: sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==} + engines: {node: '>=8'} + resolve-dir@1.0.1: resolution: {integrity: sha512-R7uiTjECzvOsWSfdM0QKFNBVFcK27aHOUwdvK53BcW8zqnGdYp0Fbj82cy54+2A4P2tFM22J5kRfe1R+lM/1yg==} engines: {node: '>=0.10.0'} @@ -2146,9 +2966,17 @@ packages: resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} engines: {node: '>=4'} + resolve-from@5.0.0: + resolution: {integrity: sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==} + engines: {node: '>=8'} + resolve-pkg-maps@1.0.0: resolution: {integrity: sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==} + resolve.exports@2.0.2: + resolution: {integrity: sha512-X2UW6Nw3n/aMgDVy+0rSqgHlv39WZAlZrXCdnbyEiKm17DSqHX4MmQMaST3FbeWR5FTuRcUwYAziZajji0Y7mg==} + engines: {node: '>=10'} + resolve@1.22.8: resolution: {integrity: sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==} hasBin: true @@ -2203,6 +3031,10 @@ packages: resolution: {integrity: sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==} hasBin: true + semver@6.3.1: + resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} + hasBin: true + semver@7.5.4: resolution: {integrity: sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==} engines: {node: '>=10'} @@ -2238,6 +3070,9 @@ packages: simple-git@3.27.0: resolution: {integrity: sha512-ivHoFS9Yi9GY49ogc6/YAi3Fl9ROnF4VyubNylgCkA+RVqLaKWnDSzXOVzya8csELIaWaYNutsEuAhZrtOjozA==} + sisteransi@1.0.5: + resolution: {integrity: sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==} + slash@3.0.0: resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} engines: {node: '>=8'} @@ -2249,6 +3084,9 @@ packages: resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} engines: {node: '>=0.10.0'} + source-map-support@0.5.13: + resolution: {integrity: sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==} + source-map@0.6.1: resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} engines: {node: '>=0.10.0'} @@ -2278,10 +3116,18 @@ packages: stable-hash@0.0.4: resolution: {integrity: sha512-LjdcbuBeLcdETCrPn9i8AYAZ1eCtu4ECAWtP7UleOiZ9LzVxRzzUZEoZ8zB24nhkQnDWyET0I+3sWokSDS3E7g==} + stack-utils@2.0.6: + resolution: {integrity: sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==} + engines: {node: '>=10'} + string-argv@0.3.2: resolution: {integrity: sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q==} engines: {node: '>=0.6.19'} + string-length@4.0.2: + resolution: {integrity: sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==} + engines: {node: '>=10'} + string-width@4.2.3: resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} engines: {node: '>=8'} @@ -2299,6 +3145,10 @@ packages: resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} engines: {node: '>=8'} + strip-bom@4.0.0: + resolution: {integrity: sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==} + engines: {node: '>=8'} + strip-eof@1.0.0: resolution: {integrity: sha512-7FCwGGmx8mD5xQd3RPUvnSpUXHM3BWuzjtpD4TXsfcZ9EL4azvVVUscFYwD9nx8Kh+uCBC00XBtAykoMHwTh8Q==} engines: {node: '>=0.10.0'} @@ -2342,6 +3192,10 @@ packages: resolution: {integrity: sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==} engines: {node: '>=6'} + test-exclude@6.0.0: + resolution: {integrity: sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==} + engines: {node: '>=8'} + text-encoding-utf-8@1.0.2: resolution: {integrity: sha512-8bw4MY9WjdsD2aMtO0OzOCY3pXGYNx2d2FfHRVUKkiCPDWjKuOlhLVASS+pD7VkLTVjW268LYJHwsnPFlBpbAg==} @@ -2369,6 +3223,9 @@ packages: resolution: {integrity: sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==} engines: {node: '>=0.6.0'} + tmpl@1.0.5: + resolution: {integrity: sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==} + to-regex-range@5.0.1: resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} engines: {node: '>=8.0'} @@ -2392,6 +3249,30 @@ packages: peerDependencies: typescript: '>=4.2.0' + ts-jest@29.2.5: + resolution: {integrity: sha512-KD8zB2aAZrcKIdGk4OwpJggeLcH1FgrICqDSROWqlnJXGCXK4Mn6FcdK2B6670Xr73lHMG1kHw8R87A0ecZ+vA==} + engines: {node: ^14.15.0 || ^16.10.0 || ^18.0.0 || >=20.0.0} + hasBin: true + peerDependencies: + '@babel/core': '>=7.0.0-beta.0 <8' + '@jest/transform': ^29.0.0 + '@jest/types': ^29.0.0 + babel-jest: ^29.0.0 + esbuild: '*' + jest: ^29.0.0 + typescript: '>=4.3 <6' + peerDependenciesMeta: + '@babel/core': + optional: true + '@jest/transform': + optional: true + '@jest/types': + optional: true + babel-jest: + optional: true + esbuild: + optional: true + ts-node@10.9.2: resolution: {integrity: sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==} hasBin: true @@ -2432,6 +3313,10 @@ packages: resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} engines: {node: '>= 0.8.0'} + type-detect@4.0.8: + resolution: {integrity: sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==} + engines: {node: '>=4'} + type-fest@0.18.1: resolution: {integrity: sha512-OIAYXk8+ISY+qTOwkHtKqzAuxchoMiD9Udx+FSGQDuiRR+PJKJHc2NJAXlbhkGwTt/4/nKZxELY1w3ReWOL8mw==} engines: {node: '>=10'} @@ -2534,6 +3419,12 @@ packages: resolution: {integrity: sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw==} engines: {node: '>=8'} + update-browserslist-db@1.1.1: + resolution: {integrity: sha512-R8UzCaa9Az+38REPiJ1tXlImTJXlVfgHZsglwBD/k6nj76ctsH1E3q4doGrukiLQd3sGQYu56r5+lo5r94l29A==} + hasBin: true + peerDependencies: + browserslist: '>= 4.21.0' + uri-js@4.4.1: resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} @@ -2551,6 +3442,10 @@ packages: v8-compile-cache-lib@3.0.1: resolution: {integrity: sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==} + v8-to-istanbul@9.3.0: + resolution: {integrity: sha512-kiGUalWN+rgBJ/1OHZsBtU4rXZOfj/7rKQxULKlIzwzQSvMJUUNgPwJEEh7gU6xEVxC0ahoOBvN2YI8GH6FNgA==} + engines: {node: '>=10.12.0'} + v8flags@4.0.1: resolution: {integrity: sha512-fcRLaS4H/hrZk9hYwbdRM35D0U8IYMfEClhXxCivOojl+yTRAZH3Zy2sSy6qVCiGbV9YAtPssP6jaChqC9vPCg==} engines: {node: '>= 10.13.0'} @@ -2627,6 +3522,9 @@ packages: peerDependencies: typescript: '>=5.0.0' + walker@1.0.8: + resolution: {integrity: sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==} + webidl-conversions@3.0.1: resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==} @@ -2692,6 +3590,9 @@ packages: yallist@2.1.2: resolution: {integrity: sha512-ncTzHV7NvsQZkYe1DW7cbDLm0YpzHmZF5r/iyP3ZnQtMiJ+pjzisCiMNI+Sj+xQF5pXhSHxSB3uDbsBTzY/c2A==} + yallist@3.1.1: + resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==} + yallist@4.0.0: resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} @@ -2704,10 +3605,18 @@ packages: resolution: {integrity: sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==} engines: {node: '>=10'} + yargs-parser@21.1.1: + resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==} + engines: {node: '>=12'} + yargs@16.2.0: resolution: {integrity: sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==} engines: {node: '>=10'} + yargs@17.7.2: + resolution: {integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==} + engines: {node: '>=12'} + yn@3.1.1: resolution: {integrity: sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==} engines: {node: '>=6'} @@ -2721,29 +3630,206 @@ packages: snapshots: + '@ampproject/remapping@2.3.0': + dependencies: + '@jridgewell/gen-mapping': 0.3.5 + '@jridgewell/trace-mapping': 0.3.25 + '@babel/code-frame@7.26.0': dependencies: '@babel/helper-validator-identifier': 7.25.9 js-tokens: 4.0.0 picocolors: 1.1.1 + '@babel/compat-data@7.26.2': {} + + '@babel/core@7.26.0': + dependencies: + '@ampproject/remapping': 2.3.0 + '@babel/code-frame': 7.26.0 + '@babel/generator': 7.26.2 + '@babel/helper-compilation-targets': 7.25.9 + '@babel/helper-module-transforms': 7.26.0(@babel/core@7.26.0) + '@babel/helpers': 7.26.0 + '@babel/parser': 7.26.0 + '@babel/template': 7.25.9 + '@babel/traverse': 7.25.9 + '@babel/types': 7.26.0 + convert-source-map: 2.0.0 + debug: 4.3.7 + gensync: 1.0.0-beta.2 + json5: 2.2.3 + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + + '@babel/generator@7.26.2': + dependencies: + '@babel/parser': 7.26.2 + '@babel/types': 7.26.0 + '@jridgewell/gen-mapping': 0.3.5 + '@jridgewell/trace-mapping': 0.3.25 + jsesc: 3.0.2 + + '@babel/helper-compilation-targets@7.25.9': + dependencies: + '@babel/compat-data': 7.26.2 + '@babel/helper-validator-option': 7.25.9 + browserslist: 4.24.2 + lru-cache: 5.1.1 + semver: 6.3.1 + + '@babel/helper-module-imports@7.25.9': + dependencies: + '@babel/traverse': 7.25.9 + '@babel/types': 7.26.0 + transitivePeerDependencies: + - supports-color + + '@babel/helper-module-transforms@7.26.0(@babel/core@7.26.0)': + dependencies: + '@babel/core': 7.26.0 + '@babel/helper-module-imports': 7.25.9 + '@babel/helper-validator-identifier': 7.25.9 + '@babel/traverse': 7.25.9 + transitivePeerDependencies: + - supports-color + + '@babel/helper-plugin-utils@7.25.9': {} + '@babel/helper-string-parser@7.25.9': {} '@babel/helper-validator-identifier@7.25.9': {} + '@babel/helper-validator-option@7.25.9': {} + + '@babel/helpers@7.26.0': + dependencies: + '@babel/template': 7.25.9 + '@babel/types': 7.26.0 + '@babel/parser@7.26.0': dependencies: '@babel/types': 7.26.0 + '@babel/parser@7.26.2': + dependencies: + '@babel/types': 7.26.0 + + '@babel/plugin-syntax-async-generators@7.8.4(@babel/core@7.26.0)': + dependencies: + '@babel/core': 7.26.0 + '@babel/helper-plugin-utils': 7.25.9 + + '@babel/plugin-syntax-bigint@7.8.3(@babel/core@7.26.0)': + dependencies: + '@babel/core': 7.26.0 + '@babel/helper-plugin-utils': 7.25.9 + + '@babel/plugin-syntax-class-properties@7.12.13(@babel/core@7.26.0)': + dependencies: + '@babel/core': 7.26.0 + '@babel/helper-plugin-utils': 7.25.9 + + '@babel/plugin-syntax-class-static-block@7.14.5(@babel/core@7.26.0)': + dependencies: + '@babel/core': 7.26.0 + '@babel/helper-plugin-utils': 7.25.9 + + '@babel/plugin-syntax-import-attributes@7.26.0(@babel/core@7.26.0)': + dependencies: + '@babel/core': 7.26.0 + '@babel/helper-plugin-utils': 7.25.9 + + '@babel/plugin-syntax-import-meta@7.10.4(@babel/core@7.26.0)': + dependencies: + '@babel/core': 7.26.0 + '@babel/helper-plugin-utils': 7.25.9 + + '@babel/plugin-syntax-json-strings@7.8.3(@babel/core@7.26.0)': + dependencies: + '@babel/core': 7.26.0 + '@babel/helper-plugin-utils': 7.25.9 + + '@babel/plugin-syntax-jsx@7.25.9(@babel/core@7.26.0)': + dependencies: + '@babel/core': 7.26.0 + '@babel/helper-plugin-utils': 7.25.9 + + '@babel/plugin-syntax-logical-assignment-operators@7.10.4(@babel/core@7.26.0)': + dependencies: + '@babel/core': 7.26.0 + '@babel/helper-plugin-utils': 7.25.9 + + '@babel/plugin-syntax-nullish-coalescing-operator@7.8.3(@babel/core@7.26.0)': + dependencies: + '@babel/core': 7.26.0 + '@babel/helper-plugin-utils': 7.25.9 + + '@babel/plugin-syntax-numeric-separator@7.10.4(@babel/core@7.26.0)': + dependencies: + '@babel/core': 7.26.0 + '@babel/helper-plugin-utils': 7.25.9 + + '@babel/plugin-syntax-object-rest-spread@7.8.3(@babel/core@7.26.0)': + dependencies: + '@babel/core': 7.26.0 + '@babel/helper-plugin-utils': 7.25.9 + + '@babel/plugin-syntax-optional-catch-binding@7.8.3(@babel/core@7.26.0)': + dependencies: + '@babel/core': 7.26.0 + '@babel/helper-plugin-utils': 7.25.9 + + '@babel/plugin-syntax-optional-chaining@7.8.3(@babel/core@7.26.0)': + dependencies: + '@babel/core': 7.26.0 + '@babel/helper-plugin-utils': 7.25.9 + + '@babel/plugin-syntax-private-property-in-object@7.14.5(@babel/core@7.26.0)': + dependencies: + '@babel/core': 7.26.0 + '@babel/helper-plugin-utils': 7.25.9 + + '@babel/plugin-syntax-top-level-await@7.14.5(@babel/core@7.26.0)': + dependencies: + '@babel/core': 7.26.0 + '@babel/helper-plugin-utils': 7.25.9 + + '@babel/plugin-syntax-typescript@7.25.9(@babel/core@7.26.0)': + dependencies: + '@babel/core': 7.26.0 + '@babel/helper-plugin-utils': 7.25.9 + '@babel/runtime@7.26.0': dependencies: regenerator-runtime: 0.14.1 + '@babel/template@7.25.9': + dependencies: + '@babel/code-frame': 7.26.0 + '@babel/parser': 7.26.0 + '@babel/types': 7.26.0 + + '@babel/traverse@7.25.9': + dependencies: + '@babel/code-frame': 7.26.0 + '@babel/generator': 7.26.2 + '@babel/parser': 7.26.0 + '@babel/template': 7.25.9 + '@babel/types': 7.26.0 + debug: 4.3.7 + globals: 11.12.0 + transitivePeerDependencies: + - supports-color + '@babel/types@7.26.0': dependencies: '@babel/helper-string-parser': 7.25.9 '@babel/helper-validator-identifier': 7.25.9 + '@bcoe/v8-coverage@0.2.3': {} + '@commitlint/parse@19.5.0': dependencies: '@commitlint/types': 19.5.0 @@ -2895,10 +3981,195 @@ snapshots: '@humanwhocodes/object-schema@2.0.3': {} + '@istanbuljs/load-nyc-config@1.1.0': + dependencies: + camelcase: 5.3.1 + find-up: 4.1.0 + get-package-type: 0.1.0 + js-yaml: 3.14.1 + resolve-from: 5.0.0 + + '@istanbuljs/schema@0.1.3': {} + + '@jest/console@29.7.0': + dependencies: + '@jest/types': 29.6.3 + '@types/node': 22.8.0 + chalk: 4.1.2 + jest-message-util: 29.7.0 + jest-util: 29.7.0 + slash: 3.0.0 + + '@jest/core@29.7.0(ts-node@10.9.2(@types/node@22.8.0)(typescript@5.6.3))': + dependencies: + '@jest/console': 29.7.0 + '@jest/reporters': 29.7.0 + '@jest/test-result': 29.7.0 + '@jest/transform': 29.7.0 + '@jest/types': 29.6.3 + '@types/node': 22.8.0 + ansi-escapes: 4.3.2 + chalk: 4.1.2 + ci-info: 3.9.0 + exit: 0.1.2 + graceful-fs: 4.2.11 + jest-changed-files: 29.7.0 + jest-config: 29.7.0(@types/node@22.8.0)(ts-node@10.9.2(@types/node@22.8.0)(typescript@5.6.3)) + jest-haste-map: 29.7.0 + jest-message-util: 29.7.0 + jest-regex-util: 29.6.3 + jest-resolve: 29.7.0 + jest-resolve-dependencies: 29.7.0 + jest-runner: 29.7.0 + jest-runtime: 29.7.0 + jest-snapshot: 29.7.0 + jest-util: 29.7.0 + jest-validate: 29.7.0 + jest-watcher: 29.7.0 + micromatch: 4.0.8 + pretty-format: 29.7.0 + slash: 3.0.0 + strip-ansi: 6.0.1 + transitivePeerDependencies: + - babel-plugin-macros + - supports-color + - ts-node + + '@jest/environment@29.7.0': + dependencies: + '@jest/fake-timers': 29.7.0 + '@jest/types': 29.6.3 + '@types/node': 22.8.0 + jest-mock: 29.7.0 + + '@jest/expect-utils@29.7.0': + dependencies: + jest-get-type: 29.6.3 + + '@jest/expect@29.7.0': + dependencies: + expect: 29.7.0 + jest-snapshot: 29.7.0 + transitivePeerDependencies: + - supports-color + + '@jest/fake-timers@29.7.0': + dependencies: + '@jest/types': 29.6.3 + '@sinonjs/fake-timers': 10.3.0 + '@types/node': 22.8.0 + jest-message-util: 29.7.0 + jest-mock: 29.7.0 + jest-util: 29.7.0 + + '@jest/globals@29.7.0': + dependencies: + '@jest/environment': 29.7.0 + '@jest/expect': 29.7.0 + '@jest/types': 29.6.3 + jest-mock: 29.7.0 + transitivePeerDependencies: + - supports-color + + '@jest/reporters@29.7.0': + dependencies: + '@bcoe/v8-coverage': 0.2.3 + '@jest/console': 29.7.0 + '@jest/test-result': 29.7.0 + '@jest/transform': 29.7.0 + '@jest/types': 29.6.3 + '@jridgewell/trace-mapping': 0.3.25 + '@types/node': 22.8.0 + chalk: 4.1.2 + collect-v8-coverage: 1.0.2 + exit: 0.1.2 + glob: 7.2.3 + graceful-fs: 4.2.11 + istanbul-lib-coverage: 3.2.2 + istanbul-lib-instrument: 6.0.3 + istanbul-lib-report: 3.0.1 + istanbul-lib-source-maps: 4.0.1 + istanbul-reports: 3.1.7 + jest-message-util: 29.7.0 + jest-util: 29.7.0 + jest-worker: 29.7.0 + slash: 3.0.0 + string-length: 4.0.2 + strip-ansi: 6.0.1 + v8-to-istanbul: 9.3.0 + transitivePeerDependencies: + - supports-color + + '@jest/schemas@29.6.3': + dependencies: + '@sinclair/typebox': 0.27.8 + + '@jest/source-map@29.6.3': + dependencies: + '@jridgewell/trace-mapping': 0.3.25 + callsites: 3.1.0 + graceful-fs: 4.2.11 + + '@jest/test-result@29.7.0': + dependencies: + '@jest/console': 29.7.0 + '@jest/types': 29.6.3 + '@types/istanbul-lib-coverage': 2.0.6 + collect-v8-coverage: 1.0.2 + + '@jest/test-sequencer@29.7.0': + dependencies: + '@jest/test-result': 29.7.0 + graceful-fs: 4.2.11 + jest-haste-map: 29.7.0 + slash: 3.0.0 + + '@jest/transform@29.7.0': + dependencies: + '@babel/core': 7.26.0 + '@jest/types': 29.6.3 + '@jridgewell/trace-mapping': 0.3.25 + babel-plugin-istanbul: 6.1.1 + chalk: 4.1.2 + convert-source-map: 2.0.0 + fast-json-stable-stringify: 2.1.0 + graceful-fs: 4.2.11 + jest-haste-map: 29.7.0 + jest-regex-util: 29.6.3 + jest-util: 29.7.0 + micromatch: 4.0.8 + pirates: 4.0.6 + slash: 3.0.0 + write-file-atomic: 4.0.2 + transitivePeerDependencies: + - supports-color + + '@jest/types@29.6.3': + dependencies: + '@jest/schemas': 29.6.3 + '@types/istanbul-lib-coverage': 2.0.6 + '@types/istanbul-reports': 3.0.4 + '@types/node': 22.8.0 + '@types/yargs': 17.0.33 + chalk: 4.1.2 + + '@jridgewell/gen-mapping@0.3.5': + dependencies: + '@jridgewell/set-array': 1.2.1 + '@jridgewell/sourcemap-codec': 1.5.0 + '@jridgewell/trace-mapping': 0.3.25 + '@jridgewell/resolve-uri@3.1.2': {} + '@jridgewell/set-array@1.2.1': {} + '@jridgewell/sourcemap-codec@1.5.0': {} + '@jridgewell/trace-mapping@0.3.25': + dependencies: + '@jridgewell/resolve-uri': 3.1.2 + '@jridgewell/sourcemap-codec': 1.5.0 + '@jridgewell/trace-mapping@0.3.9': dependencies: '@jridgewell/resolve-uri': 3.1.2 @@ -2912,6 +4183,108 @@ snapshots: '@kwsites/promise-deferred@1.1.1': {} + '@metaplex-foundation/mpl-token-metadata@3.3.0(@metaplex-foundation/umi@0.9.2)': + dependencies: + '@metaplex-foundation/mpl-toolbox': 0.9.4(@metaplex-foundation/umi@0.9.2) + '@metaplex-foundation/umi': 0.9.2 + + '@metaplex-foundation/mpl-toolbox@0.9.4(@metaplex-foundation/umi@0.9.2)': + dependencies: + '@metaplex-foundation/umi': 0.9.2 + + '@metaplex-foundation/umi-bundle-defaults@0.9.2(@metaplex-foundation/umi@0.9.2)(@solana/web3.js@1.95.4(bufferutil@4.0.8)(utf-8-validate@5.0.10))': + dependencies: + '@metaplex-foundation/umi': 0.9.2 + '@metaplex-foundation/umi-downloader-http': 0.9.2(@metaplex-foundation/umi@0.9.2) + '@metaplex-foundation/umi-eddsa-web3js': 0.9.2(@metaplex-foundation/umi@0.9.2)(@solana/web3.js@1.95.4(bufferutil@4.0.8)(utf-8-validate@5.0.10)) + '@metaplex-foundation/umi-http-fetch': 0.9.2(@metaplex-foundation/umi@0.9.2) + '@metaplex-foundation/umi-program-repository': 0.9.2(@metaplex-foundation/umi@0.9.2) + '@metaplex-foundation/umi-rpc-chunk-get-accounts': 0.9.2(@metaplex-foundation/umi@0.9.2) + '@metaplex-foundation/umi-rpc-web3js': 0.9.2(@metaplex-foundation/umi@0.9.2)(@solana/web3.js@1.95.4(bufferutil@4.0.8)(utf-8-validate@5.0.10)) + '@metaplex-foundation/umi-serializer-data-view': 0.9.2(@metaplex-foundation/umi@0.9.2) + '@metaplex-foundation/umi-transaction-factory-web3js': 0.9.2(@metaplex-foundation/umi@0.9.2)(@solana/web3.js@1.95.4(bufferutil@4.0.8)(utf-8-validate@5.0.10)) + '@solana/web3.js': 1.95.4(bufferutil@4.0.8)(utf-8-validate@5.0.10) + transitivePeerDependencies: + - encoding + + '@metaplex-foundation/umi-downloader-http@0.9.2(@metaplex-foundation/umi@0.9.2)': + dependencies: + '@metaplex-foundation/umi': 0.9.2 + + '@metaplex-foundation/umi-eddsa-web3js@0.9.2(@metaplex-foundation/umi@0.9.2)(@solana/web3.js@1.95.4(bufferutil@4.0.8)(utf-8-validate@5.0.10))': + dependencies: + '@metaplex-foundation/umi': 0.9.2 + '@metaplex-foundation/umi-web3js-adapters': 0.9.2(@metaplex-foundation/umi@0.9.2)(@solana/web3.js@1.95.4(bufferutil@4.0.8)(utf-8-validate@5.0.10)) + '@noble/curves': 1.6.0 + '@solana/web3.js': 1.95.4(bufferutil@4.0.8)(utf-8-validate@5.0.10) + + '@metaplex-foundation/umi-http-fetch@0.9.2(@metaplex-foundation/umi@0.9.2)': + dependencies: + '@metaplex-foundation/umi': 0.9.2 + node-fetch: 2.7.0 + transitivePeerDependencies: + - encoding + + '@metaplex-foundation/umi-options@0.8.9': {} + + '@metaplex-foundation/umi-program-repository@0.9.2(@metaplex-foundation/umi@0.9.2)': + dependencies: + '@metaplex-foundation/umi': 0.9.2 + + '@metaplex-foundation/umi-public-keys@0.8.9': + dependencies: + '@metaplex-foundation/umi-serializers-encodings': 0.8.9 + + '@metaplex-foundation/umi-rpc-chunk-get-accounts@0.9.2(@metaplex-foundation/umi@0.9.2)': + dependencies: + '@metaplex-foundation/umi': 0.9.2 + + '@metaplex-foundation/umi-rpc-web3js@0.9.2(@metaplex-foundation/umi@0.9.2)(@solana/web3.js@1.95.4(bufferutil@4.0.8)(utf-8-validate@5.0.10))': + dependencies: + '@metaplex-foundation/umi': 0.9.2 + '@metaplex-foundation/umi-web3js-adapters': 0.9.2(@metaplex-foundation/umi@0.9.2)(@solana/web3.js@1.95.4(bufferutil@4.0.8)(utf-8-validate@5.0.10)) + '@solana/web3.js': 1.95.4(bufferutil@4.0.8)(utf-8-validate@5.0.10) + + '@metaplex-foundation/umi-serializer-data-view@0.9.2(@metaplex-foundation/umi@0.9.2)': + dependencies: + '@metaplex-foundation/umi': 0.9.2 + + '@metaplex-foundation/umi-serializers-core@0.8.9': {} + + '@metaplex-foundation/umi-serializers-encodings@0.8.9': + dependencies: + '@metaplex-foundation/umi-serializers-core': 0.8.9 + + '@metaplex-foundation/umi-serializers-numbers@0.8.9': + dependencies: + '@metaplex-foundation/umi-serializers-core': 0.8.9 + + '@metaplex-foundation/umi-serializers@0.9.0': + dependencies: + '@metaplex-foundation/umi-options': 0.8.9 + '@metaplex-foundation/umi-public-keys': 0.8.9 + '@metaplex-foundation/umi-serializers-core': 0.8.9 + '@metaplex-foundation/umi-serializers-encodings': 0.8.9 + '@metaplex-foundation/umi-serializers-numbers': 0.8.9 + + '@metaplex-foundation/umi-transaction-factory-web3js@0.9.2(@metaplex-foundation/umi@0.9.2)(@solana/web3.js@1.95.4(bufferutil@4.0.8)(utf-8-validate@5.0.10))': + dependencies: + '@metaplex-foundation/umi': 0.9.2 + '@metaplex-foundation/umi-web3js-adapters': 0.9.2(@metaplex-foundation/umi@0.9.2)(@solana/web3.js@1.95.4(bufferutil@4.0.8)(utf-8-validate@5.0.10)) + '@solana/web3.js': 1.95.4(bufferutil@4.0.8)(utf-8-validate@5.0.10) + + '@metaplex-foundation/umi-web3js-adapters@0.9.2(@metaplex-foundation/umi@0.9.2)(@solana/web3.js@1.95.4(bufferutil@4.0.8)(utf-8-validate@5.0.10))': + dependencies: + '@metaplex-foundation/umi': 0.9.2 + '@solana/web3.js': 1.95.4(bufferutil@4.0.8)(utf-8-validate@5.0.10) + buffer: 6.0.3 + + '@metaplex-foundation/umi@0.9.2': + dependencies: + '@metaplex-foundation/umi-options': 0.8.9 + '@metaplex-foundation/umi-public-keys': 0.8.9 + '@metaplex-foundation/umi-serializers': 0.9.0 + '@microsoft/api-extractor-model@7.29.4(@types/node@22.8.0)': dependencies: '@microsoft/tsdoc': 0.15.0 @@ -3084,6 +4457,16 @@ snapshots: '@shikijs/vscode-textmate@9.3.0': {} + '@sinclair/typebox@0.27.8': {} + + '@sinonjs/commons@3.0.1': + dependencies: + type-detect: 4.0.8 + + '@sinonjs/fake-timers@10.3.0': + dependencies: + '@sinonjs/commons': 3.0.1 + '@solana/buffer-layout-utils@0.2.0(bufferutil@4.0.8)(utf-8-validate@5.0.10)': dependencies: '@solana/buffer-layout': 4.0.1 @@ -3261,6 +4644,27 @@ snapshots: '@types/argparse@1.0.38': {} + '@types/babel__core@7.20.5': + dependencies: + '@babel/parser': 7.26.0 + '@babel/types': 7.26.0 + '@types/babel__generator': 7.6.8 + '@types/babel__template': 7.4.4 + '@types/babel__traverse': 7.20.6 + + '@types/babel__generator@7.6.8': + dependencies: + '@babel/types': 7.26.0 + + '@types/babel__template@7.4.4': + dependencies: + '@babel/parser': 7.26.0 + '@babel/types': 7.26.0 + + '@types/babel__traverse@7.20.6': + dependencies: + '@babel/types': 7.26.0 + '@types/bn.js@5.1.6': dependencies: '@types/node': 22.8.0 @@ -3277,10 +4681,29 @@ snapshots: '@types/expand-tilde@2.0.2': {} + '@types/graceful-fs@4.1.9': + dependencies: + '@types/node': 22.8.0 + '@types/hast@3.0.4': dependencies: '@types/unist': 3.0.3 + '@types/istanbul-lib-coverage@2.0.6': {} + + '@types/istanbul-lib-report@3.0.3': + dependencies: + '@types/istanbul-lib-coverage': 2.0.6 + + '@types/istanbul-reports@3.0.4': + dependencies: + '@types/istanbul-lib-report': 3.0.3 + + '@types/jest@29.5.14': + dependencies: + expect: 29.7.0 + pretty-format: 29.7.0 + '@types/json-schema@7.0.15': {} '@types/mdast@4.0.4': @@ -3303,6 +4726,8 @@ snapshots: '@types/semver@7.5.8': {} + '@types/stack-utils@2.0.3': {} + '@types/unist@3.0.3': {} '@types/uuid@8.3.4': {} @@ -3315,6 +4740,12 @@ snapshots: dependencies: '@types/node': 22.8.0 + '@types/yargs-parser@21.0.3': {} + + '@types/yargs@17.0.33': + dependencies: + '@types/yargs-parser': 21.0.3 + '@typescript-eslint/eslint-plugin@5.62.0(@typescript-eslint/parser@5.62.0(eslint@8.57.1)(typescript@5.6.3))(eslint@8.57.1)(typescript@5.6.3)': dependencies: '@eslint-community/regexpp': 4.11.1 @@ -3585,8 +5016,15 @@ snapshots: dependencies: color-convert: 2.0.1 + ansi-styles@5.2.0: {} + any-promise@1.3.0: {} + anymatch@3.1.3: + dependencies: + normalize-path: 3.0.0 + picomatch: 2.3.1 + arg@4.1.3: {} argparse@1.0.10: @@ -3605,8 +5043,65 @@ snapshots: arrify@1.0.1: {} + async@3.2.6: {} + + babel-jest@29.7.0(@babel/core@7.26.0): + dependencies: + '@babel/core': 7.26.0 + '@jest/transform': 29.7.0 + '@types/babel__core': 7.20.5 + babel-plugin-istanbul: 6.1.1 + babel-preset-jest: 29.6.3(@babel/core@7.26.0) + chalk: 4.1.2 + graceful-fs: 4.2.11 + slash: 3.0.0 + transitivePeerDependencies: + - supports-color + babel-plugin-add-module-exports@0.2.1: {} + babel-plugin-istanbul@6.1.1: + dependencies: + '@babel/helper-plugin-utils': 7.25.9 + '@istanbuljs/load-nyc-config': 1.1.0 + '@istanbuljs/schema': 0.1.3 + istanbul-lib-instrument: 5.2.1 + test-exclude: 6.0.0 + transitivePeerDependencies: + - supports-color + + babel-plugin-jest-hoist@29.6.3: + dependencies: + '@babel/template': 7.25.9 + '@babel/types': 7.26.0 + '@types/babel__core': 7.20.5 + '@types/babel__traverse': 7.20.6 + + babel-preset-current-node-syntax@1.1.0(@babel/core@7.26.0): + dependencies: + '@babel/core': 7.26.0 + '@babel/plugin-syntax-async-generators': 7.8.4(@babel/core@7.26.0) + '@babel/plugin-syntax-bigint': 7.8.3(@babel/core@7.26.0) + '@babel/plugin-syntax-class-properties': 7.12.13(@babel/core@7.26.0) + '@babel/plugin-syntax-class-static-block': 7.14.5(@babel/core@7.26.0) + '@babel/plugin-syntax-import-attributes': 7.26.0(@babel/core@7.26.0) + '@babel/plugin-syntax-import-meta': 7.10.4(@babel/core@7.26.0) + '@babel/plugin-syntax-json-strings': 7.8.3(@babel/core@7.26.0) + '@babel/plugin-syntax-logical-assignment-operators': 7.10.4(@babel/core@7.26.0) + '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3(@babel/core@7.26.0) + '@babel/plugin-syntax-numeric-separator': 7.10.4(@babel/core@7.26.0) + '@babel/plugin-syntax-object-rest-spread': 7.8.3(@babel/core@7.26.0) + '@babel/plugin-syntax-optional-catch-binding': 7.8.3(@babel/core@7.26.0) + '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.26.0) + '@babel/plugin-syntax-private-property-in-object': 7.14.5(@babel/core@7.26.0) + '@babel/plugin-syntax-top-level-await': 7.14.5(@babel/core@7.26.0) + + babel-preset-jest@29.6.3(@babel/core@7.26.0): + dependencies: + '@babel/core': 7.26.0 + babel-plugin-jest-hoist: 29.6.3 + babel-preset-current-node-syntax: 1.1.0(@babel/core@7.26.0) + balanced-match@1.0.2: {} base-x@3.0.10: @@ -3646,10 +5141,27 @@ snapshots: dependencies: fill-range: 7.1.1 + browserslist@4.24.2: + dependencies: + caniuse-lite: 1.0.30001683 + electron-to-chromium: 1.5.64 + node-releases: 2.0.18 + update-browserslist-db: 1.1.1(browserslist@4.24.2) + + bs-logger@0.2.6: + dependencies: + fast-json-stable-stringify: 2.1.0 + bs58@4.0.1: dependencies: base-x: 3.0.10 + bser@2.1.1: + dependencies: + node-int64: 0.4.0 + + buffer-from@1.1.2: {} + buffer-layout@1.2.2: {} buffer@6.0.3: @@ -3678,6 +5190,8 @@ snapshots: camelcase@6.3.0: {} + caniuse-lite@1.0.30001683: {} + ccount@2.0.1: {} chalk@4.1.2: @@ -3687,12 +5201,18 @@ snapshots: chalk@5.3.0: {} + char-regex@1.0.2: {} + character-entities-html4@2.1.0: {} character-entities-legacy@3.0.0: {} chardet@0.7.0: {} + ci-info@3.9.0: {} + + cjs-module-lexer@1.4.1: {} + cli-cursor@3.1.0: dependencies: restore-cursor: 3.1.0 @@ -3705,6 +5225,16 @@ snapshots: strip-ansi: 6.0.1 wrap-ansi: 7.0.0 + cliui@8.0.1: + dependencies: + string-width: 4.2.3 + strip-ansi: 6.0.1 + wrap-ansi: 7.0.0 + + co@4.6.0: {} + + collect-v8-coverage@1.0.2: {} + color-convert@2.0.1: dependencies: color-name: 1.1.4 @@ -3741,6 +5271,8 @@ snapshots: meow: 12.1.1 split2: 4.2.0 + convert-source-map@2.0.0: {} + copyfiles@2.4.1: dependencies: glob: 7.2.3 @@ -3753,6 +5285,21 @@ snapshots: core-util-is@1.0.3: {} + create-jest@29.7.0(@types/node@22.8.0)(ts-node@10.9.2(@types/node@22.8.0)(typescript@5.6.3)): + dependencies: + '@jest/types': 29.6.3 + chalk: 4.1.2 + exit: 0.1.2 + graceful-fs: 4.2.11 + jest-config: 29.7.0(@types/node@22.8.0)(ts-node@10.9.2(@types/node@22.8.0)(typescript@5.6.3)) + jest-util: 29.7.0 + prompts: 2.4.2 + transitivePeerDependencies: + - '@types/node' + - babel-plugin-macros + - supports-color + - ts-node + create-require@1.1.1: {} cross-fetch@3.1.8: @@ -3798,18 +5345,26 @@ snapshots: decamelize@1.2.0: {} + dedent@1.5.3: {} + deep-is@0.1.4: {} + deepmerge@4.3.1: {} + delay@5.0.0: {} dequal@2.0.3: {} detect-file@1.0.0: {} + detect-newline@3.1.0: {} + devlop@1.1.0: dependencies: dequal: 2.0.3 + diff-sequences@29.6.3: {} + diff@4.0.2: {} dir-glob@3.0.1: @@ -3829,6 +5384,14 @@ snapshots: dependencies: is-obj: 2.0.0 + ejs@3.1.10: + dependencies: + jake: 10.9.2 + + electron-to-chromium@1.5.64: {} + + emittery@0.13.1: {} + emoji-regex@8.0.0: {} enhanced-resolve@5.17.1: @@ -3885,6 +5448,8 @@ snapshots: escape-string-regexp@1.0.5: {} + escape-string-regexp@2.0.0: {} + escape-string-regexp@4.0.0: {} eslint-compat-utils@0.5.1(eslint@8.57.1): @@ -4049,6 +5614,8 @@ snapshots: acorn-jsx: 5.3.2(acorn@8.13.0) eslint-visitor-keys: 3.4.3 + esprima@4.0.1: {} + esquery@1.6.0: dependencies: estraverse: 5.3.0 @@ -4091,10 +5658,20 @@ snapshots: signal-exit: 3.0.7 strip-final-newline: 2.0.0 + exit@0.1.2: {} + expand-tilde@2.0.2: dependencies: homedir-polyfill: 1.0.3 + expect@29.7.0: + dependencies: + '@jest/expect-utils': 29.7.0 + jest-get-type: 29.6.3 + jest-matcher-utils: 29.7.0 + jest-message-util: 29.7.0 + jest-util: 29.7.0 + extend@3.0.2: {} external-editor@3.1.0: @@ -4129,6 +5706,10 @@ snapshots: dependencies: reusify: 1.0.4 + fb-watchman@2.0.2: + dependencies: + bser: 2.1.1 + figures@3.2.0: dependencies: escape-string-regexp: 1.0.5 @@ -4139,6 +5720,10 @@ snapshots: file-uri-to-path@1.0.0: {} + filelist@1.0.4: + dependencies: + minimatch: 5.1.6 + fill-range@7.1.1: dependencies: to-regex-range: 5.0.1 @@ -4197,8 +5782,12 @@ snapshots: function-bind@1.1.2: {} + gensync@1.0.0-beta.2: {} + get-caller-file@2.0.5: {} + get-package-type@0.1.0: {} + get-stream@3.0.0: {} get-stream@6.0.1: {} @@ -4238,6 +5827,8 @@ snapshots: is-windows: 1.0.2 which: 1.3.1 + globals@11.12.0: {} + globals@13.24.0: dependencies: type-fest: 0.20.2 @@ -4319,6 +5910,8 @@ snapshots: dependencies: lru-cache: 6.0.0 + html-escaper@2.0.2: {} + html-void-elements@3.0.0: {} human-signals@2.1.0: {} @@ -4342,6 +5935,11 @@ snapshots: import-lazy@4.0.0: {} + import-local@3.2.0: + dependencies: + pkg-dir: 4.2.0 + resolve-cwd: 3.0.0 + imurmurhash@0.1.4: {} indent-string@4.0.0: {} @@ -4388,6 +5986,8 @@ snapshots: is-fullwidth-code-point@3.0.0: {} + is-generator-fn@2.1.0: {} + is-git-repository@1.1.1: dependencies: execa: 0.6.3 @@ -4437,6 +6037,54 @@ snapshots: dependencies: ws: 7.5.10(bufferutil@4.0.8)(utf-8-validate@5.0.10) + istanbul-lib-coverage@3.2.2: {} + + istanbul-lib-instrument@5.2.1: + dependencies: + '@babel/core': 7.26.0 + '@babel/parser': 7.26.0 + '@istanbuljs/schema': 0.1.3 + istanbul-lib-coverage: 3.2.2 + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + + istanbul-lib-instrument@6.0.3: + dependencies: + '@babel/core': 7.26.0 + '@babel/parser': 7.26.0 + '@istanbuljs/schema': 0.1.3 + istanbul-lib-coverage: 3.2.2 + semver: 7.6.3 + transitivePeerDependencies: + - supports-color + + istanbul-lib-report@3.0.1: + dependencies: + istanbul-lib-coverage: 3.2.2 + make-dir: 4.0.0 + supports-color: 7.2.0 + + istanbul-lib-source-maps@4.0.1: + dependencies: + debug: 4.3.7 + istanbul-lib-coverage: 3.2.2 + source-map: 0.6.1 + transitivePeerDependencies: + - supports-color + + istanbul-reports@3.1.7: + dependencies: + html-escaper: 2.0.2 + istanbul-lib-report: 3.0.1 + + jake@10.9.2: + dependencies: + async: 3.2.6 + chalk: 4.1.2 + filelist: 1.0.4 + minimatch: 3.1.2 + jayson@4.1.2(bufferutil@4.0.8)(utf-8-validate@5.0.10): dependencies: '@types/connect': 3.4.38 @@ -4455,14 +6103,332 @@ snapshots: - bufferutil - utf-8-validate + jest-changed-files@29.7.0: + dependencies: + execa: 5.1.1 + jest-util: 29.7.0 + p-limit: 3.1.0 + + jest-circus@29.7.0: + dependencies: + '@jest/environment': 29.7.0 + '@jest/expect': 29.7.0 + '@jest/test-result': 29.7.0 + '@jest/types': 29.6.3 + '@types/node': 22.8.0 + chalk: 4.1.2 + co: 4.6.0 + dedent: 1.5.3 + is-generator-fn: 2.1.0 + jest-each: 29.7.0 + jest-matcher-utils: 29.7.0 + jest-message-util: 29.7.0 + jest-runtime: 29.7.0 + jest-snapshot: 29.7.0 + jest-util: 29.7.0 + p-limit: 3.1.0 + pretty-format: 29.7.0 + pure-rand: 6.1.0 + slash: 3.0.0 + stack-utils: 2.0.6 + transitivePeerDependencies: + - babel-plugin-macros + - supports-color + + jest-cli@29.7.0(@types/node@22.8.0)(ts-node@10.9.2(@types/node@22.8.0)(typescript@5.6.3)): + dependencies: + '@jest/core': 29.7.0(ts-node@10.9.2(@types/node@22.8.0)(typescript@5.6.3)) + '@jest/test-result': 29.7.0 + '@jest/types': 29.6.3 + chalk: 4.1.2 + create-jest: 29.7.0(@types/node@22.8.0)(ts-node@10.9.2(@types/node@22.8.0)(typescript@5.6.3)) + exit: 0.1.2 + import-local: 3.2.0 + jest-config: 29.7.0(@types/node@22.8.0)(ts-node@10.9.2(@types/node@22.8.0)(typescript@5.6.3)) + jest-util: 29.7.0 + jest-validate: 29.7.0 + yargs: 17.7.2 + transitivePeerDependencies: + - '@types/node' + - babel-plugin-macros + - supports-color + - ts-node + + jest-config@29.7.0(@types/node@22.8.0)(ts-node@10.9.2(@types/node@22.8.0)(typescript@5.6.3)): + dependencies: + '@babel/core': 7.26.0 + '@jest/test-sequencer': 29.7.0 + '@jest/types': 29.6.3 + babel-jest: 29.7.0(@babel/core@7.26.0) + chalk: 4.1.2 + ci-info: 3.9.0 + deepmerge: 4.3.1 + glob: 7.2.3 + graceful-fs: 4.2.11 + jest-circus: 29.7.0 + jest-environment-node: 29.7.0 + jest-get-type: 29.6.3 + jest-regex-util: 29.6.3 + jest-resolve: 29.7.0 + jest-runner: 29.7.0 + jest-util: 29.7.0 + jest-validate: 29.7.0 + micromatch: 4.0.8 + parse-json: 5.2.0 + pretty-format: 29.7.0 + slash: 3.0.0 + strip-json-comments: 3.1.1 + optionalDependencies: + '@types/node': 22.8.0 + ts-node: 10.9.2(@types/node@22.8.0)(typescript@5.6.3) + transitivePeerDependencies: + - babel-plugin-macros + - supports-color + + jest-diff@29.7.0: + dependencies: + chalk: 4.1.2 + diff-sequences: 29.6.3 + jest-get-type: 29.6.3 + pretty-format: 29.7.0 + + jest-docblock@29.7.0: + dependencies: + detect-newline: 3.1.0 + + jest-each@29.7.0: + dependencies: + '@jest/types': 29.6.3 + chalk: 4.1.2 + jest-get-type: 29.6.3 + jest-util: 29.7.0 + pretty-format: 29.7.0 + + jest-environment-node@29.7.0: + dependencies: + '@jest/environment': 29.7.0 + '@jest/fake-timers': 29.7.0 + '@jest/types': 29.6.3 + '@types/node': 22.8.0 + jest-mock: 29.7.0 + jest-util: 29.7.0 + + jest-get-type@29.6.3: {} + + jest-haste-map@29.7.0: + dependencies: + '@jest/types': 29.6.3 + '@types/graceful-fs': 4.1.9 + '@types/node': 22.8.0 + anymatch: 3.1.3 + fb-watchman: 2.0.2 + graceful-fs: 4.2.11 + jest-regex-util: 29.6.3 + jest-util: 29.7.0 + jest-worker: 29.7.0 + micromatch: 4.0.8 + walker: 1.0.8 + optionalDependencies: + fsevents: 2.3.3 + + jest-leak-detector@29.7.0: + dependencies: + jest-get-type: 29.6.3 + pretty-format: 29.7.0 + + jest-matcher-utils@29.7.0: + dependencies: + chalk: 4.1.2 + jest-diff: 29.7.0 + jest-get-type: 29.6.3 + pretty-format: 29.7.0 + + jest-message-util@29.7.0: + dependencies: + '@babel/code-frame': 7.26.0 + '@jest/types': 29.6.3 + '@types/stack-utils': 2.0.3 + chalk: 4.1.2 + graceful-fs: 4.2.11 + micromatch: 4.0.8 + pretty-format: 29.7.0 + slash: 3.0.0 + stack-utils: 2.0.6 + + jest-mock@29.7.0: + dependencies: + '@jest/types': 29.6.3 + '@types/node': 22.8.0 + jest-util: 29.7.0 + + jest-pnp-resolver@1.2.3(jest-resolve@29.7.0): + optionalDependencies: + jest-resolve: 29.7.0 + + jest-regex-util@29.6.3: {} + + jest-resolve-dependencies@29.7.0: + dependencies: + jest-regex-util: 29.6.3 + jest-snapshot: 29.7.0 + transitivePeerDependencies: + - supports-color + + jest-resolve@29.7.0: + dependencies: + chalk: 4.1.2 + graceful-fs: 4.2.11 + jest-haste-map: 29.7.0 + jest-pnp-resolver: 1.2.3(jest-resolve@29.7.0) + jest-util: 29.7.0 + jest-validate: 29.7.0 + resolve: 1.22.8 + resolve.exports: 2.0.2 + slash: 3.0.0 + + jest-runner@29.7.0: + dependencies: + '@jest/console': 29.7.0 + '@jest/environment': 29.7.0 + '@jest/test-result': 29.7.0 + '@jest/transform': 29.7.0 + '@jest/types': 29.6.3 + '@types/node': 22.8.0 + chalk: 4.1.2 + emittery: 0.13.1 + graceful-fs: 4.2.11 + jest-docblock: 29.7.0 + jest-environment-node: 29.7.0 + jest-haste-map: 29.7.0 + jest-leak-detector: 29.7.0 + jest-message-util: 29.7.0 + jest-resolve: 29.7.0 + jest-runtime: 29.7.0 + jest-util: 29.7.0 + jest-watcher: 29.7.0 + jest-worker: 29.7.0 + p-limit: 3.1.0 + source-map-support: 0.5.13 + transitivePeerDependencies: + - supports-color + + jest-runtime@29.7.0: + dependencies: + '@jest/environment': 29.7.0 + '@jest/fake-timers': 29.7.0 + '@jest/globals': 29.7.0 + '@jest/source-map': 29.6.3 + '@jest/test-result': 29.7.0 + '@jest/transform': 29.7.0 + '@jest/types': 29.6.3 + '@types/node': 22.8.0 + chalk: 4.1.2 + cjs-module-lexer: 1.4.1 + collect-v8-coverage: 1.0.2 + glob: 7.2.3 + graceful-fs: 4.2.11 + jest-haste-map: 29.7.0 + jest-message-util: 29.7.0 + jest-mock: 29.7.0 + jest-regex-util: 29.6.3 + jest-resolve: 29.7.0 + jest-snapshot: 29.7.0 + jest-util: 29.7.0 + slash: 3.0.0 + strip-bom: 4.0.0 + transitivePeerDependencies: + - supports-color + + jest-snapshot@29.7.0: + dependencies: + '@babel/core': 7.26.0 + '@babel/generator': 7.26.2 + '@babel/plugin-syntax-jsx': 7.25.9(@babel/core@7.26.0) + '@babel/plugin-syntax-typescript': 7.25.9(@babel/core@7.26.0) + '@babel/types': 7.26.0 + '@jest/expect-utils': 29.7.0 + '@jest/transform': 29.7.0 + '@jest/types': 29.6.3 + babel-preset-current-node-syntax: 1.1.0(@babel/core@7.26.0) + chalk: 4.1.2 + expect: 29.7.0 + graceful-fs: 4.2.11 + jest-diff: 29.7.0 + jest-get-type: 29.6.3 + jest-matcher-utils: 29.7.0 + jest-message-util: 29.7.0 + jest-util: 29.7.0 + natural-compare: 1.4.0 + pretty-format: 29.7.0 + semver: 7.6.3 + transitivePeerDependencies: + - supports-color + + jest-util@29.7.0: + dependencies: + '@jest/types': 29.6.3 + '@types/node': 22.8.0 + chalk: 4.1.2 + ci-info: 3.9.0 + graceful-fs: 4.2.11 + picomatch: 2.3.1 + + jest-validate@29.7.0: + dependencies: + '@jest/types': 29.6.3 + camelcase: 6.3.0 + chalk: 4.1.2 + jest-get-type: 29.6.3 + leven: 3.1.0 + pretty-format: 29.7.0 + + jest-watcher@29.7.0: + dependencies: + '@jest/test-result': 29.7.0 + '@jest/types': 29.6.3 + '@types/node': 22.8.0 + ansi-escapes: 4.3.2 + chalk: 4.1.2 + emittery: 0.13.1 + jest-util: 29.7.0 + string-length: 4.0.2 + + jest-worker@29.7.0: + dependencies: + '@types/node': 22.8.0 + jest-util: 29.7.0 + merge-stream: 2.0.0 + supports-color: 8.1.1 + + jest@29.7.0(@types/node@22.8.0)(ts-node@10.9.2(@types/node@22.8.0)(typescript@5.6.3)): + dependencies: + '@jest/core': 29.7.0(ts-node@10.9.2(@types/node@22.8.0)(typescript@5.6.3)) + '@jest/types': 29.6.3 + import-local: 3.2.0 + jest-cli: 29.7.0(@types/node@22.8.0)(ts-node@10.9.2(@types/node@22.8.0)(typescript@5.6.3)) + transitivePeerDependencies: + - '@types/node' + - babel-plugin-macros + - supports-color + - ts-node + jju@1.4.0: {} + js-base64@3.7.7: {} + js-tokens@4.0.0: {} + js-yaml@3.14.1: + dependencies: + argparse: 1.0.10 + esprima: 4.0.1 + js-yaml@4.1.0: dependencies: argparse: 2.0.1 + jsesc@3.0.2: {} + json-buffer@3.0.1: {} json-parse-even-better-errors@2.3.1: {} @@ -4495,8 +6461,12 @@ snapshots: kind-of@6.0.3: {} + kleur@3.0.3: {} + kolorist@1.8.0: {} + leven@3.1.0: {} + levn@0.4.1: dependencies: prelude-ls: 1.2.1 @@ -4531,6 +6501,8 @@ snapshots: dependencies: p-locate: 5.0.0 + lodash.memoize@4.1.2: {} + lodash.merge@4.6.2: {} lodash@4.17.21: {} @@ -4544,6 +6516,10 @@ snapshots: pseudomap: 1.0.2 yallist: 2.1.2 + lru-cache@5.1.1: + dependencies: + yallist: 3.1.1 + lru-cache@6.0.0: dependencies: yallist: 4.0.0 @@ -4554,8 +6530,16 @@ snapshots: dependencies: '@jridgewell/sourcemap-codec': 1.5.0 + make-dir@4.0.0: + dependencies: + semver: 7.6.3 + make-error@1.3.6: {} + makeerror@1.0.12: + dependencies: + tmpl: 1.0.5 + map-cache@0.2.2: {} map-obj@1.0.1: {} @@ -4640,6 +6624,10 @@ snapshots: dependencies: brace-expansion: 1.1.11 + minimatch@5.1.6: + dependencies: + brace-expansion: 2.0.1 + minimatch@9.0.5: dependencies: brace-expansion: 2.0.1 @@ -4693,6 +6681,10 @@ snapshots: node-gyp-build@4.8.2: optional: true + node-int64@0.4.0: {} + + node-releases@2.0.18: {} + noms@0.0.0: dependencies: inherits: 2.0.4 @@ -4712,6 +6704,8 @@ snapshots: semver: 7.6.3 validate-npm-package-license: 3.0.4 + normalize-path@3.0.0: {} + npm-run-path@2.0.2: dependencies: path-key: 2.0.1 @@ -4825,6 +6819,12 @@ snapshots: picomatch@4.0.2: {} + pirates@4.0.6: {} + + pkg-dir@4.2.0: + dependencies: + find-up: 4.1.0 + pkg-types@1.2.1: dependencies: confbox: 0.1.8 @@ -4847,8 +6847,19 @@ snapshots: prettier@3.3.3: {} + pretty-format@29.7.0: + dependencies: + '@jest/schemas': 29.6.3 + ansi-styles: 5.2.0 + react-is: 18.3.1 + process-nextick-args@2.0.1: {} + prompts@2.4.2: + dependencies: + kleur: 3.0.3 + sisteransi: 1.0.5 + property-information@6.5.0: {} pseudomap@1.0.2: {} @@ -4857,10 +6868,14 @@ snapshots: punycode@2.3.1: {} + pure-rand@6.1.0: {} + queue-microtask@1.2.3: {} quick-lru@4.0.1: {} + react-is@18.3.1: {} + read-pkg-up@7.0.1: dependencies: find-up: 4.1.0 @@ -4910,6 +6925,10 @@ snapshots: require-from-string@2.0.2: {} + resolve-cwd@3.0.0: + dependencies: + resolve-from: 5.0.0 + resolve-dir@1.0.1: dependencies: expand-tilde: 2.0.2 @@ -4917,8 +6936,12 @@ snapshots: resolve-from@4.0.0: {} + resolve-from@5.0.0: {} + resolve-pkg-maps@1.0.0: {} + resolve.exports@2.0.2: {} + resolve@1.22.8: dependencies: is-core-module: 2.15.1 @@ -4995,6 +7018,8 @@ snapshots: semver@5.7.2: {} + semver@6.3.1: {} + semver@7.5.4: dependencies: lru-cache: 6.0.0 @@ -5032,6 +7057,8 @@ snapshots: transitivePeerDependencies: - supports-color + sisteransi@1.0.5: {} + slash@3.0.0: {} snake-case@3.0.4: @@ -5041,6 +7068,11 @@ snapshots: source-map-js@1.2.1: {} + source-map-support@0.5.13: + dependencies: + buffer-from: 1.1.2 + source-map: 0.6.1 + source-map@0.6.1: {} space-separated-tokens@2.0.2: {} @@ -5065,8 +7097,17 @@ snapshots: stable-hash@0.0.4: {} + stack-utils@2.0.6: + dependencies: + escape-string-regexp: 2.0.0 + string-argv@0.3.2: {} + string-length@4.0.2: + dependencies: + char-regex: 1.0.2 + strip-ansi: 6.0.1 + string-width@4.2.3: dependencies: emoji-regex: 8.0.0 @@ -5088,6 +7129,8 @@ snapshots: dependencies: ansi-regex: 5.0.1 + strip-bom@4.0.0: {} + strip-eof@1.0.0: {} strip-final-newline@2.0.0: {} @@ -5119,6 +7162,12 @@ snapshots: tapable@2.2.1: {} + test-exclude@6.0.0: + dependencies: + '@istanbuljs/schema': 0.1.3 + glob: 7.2.3 + minimatch: 3.1.2 + text-encoding-utf-8@1.0.2: {} text-extensions@2.4.0: {} @@ -5144,6 +7193,8 @@ snapshots: dependencies: os-tmpdir: 1.0.2 + tmpl@1.0.5: {} + to-regex-range@5.0.1: dependencies: is-number: 7.0.0 @@ -5160,6 +7211,25 @@ snapshots: dependencies: typescript: 5.6.3 + ts-jest@29.2.5(@babel/core@7.26.0)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.26.0))(jest@29.7.0(@types/node@22.8.0)(ts-node@10.9.2(@types/node@22.8.0)(typescript@5.6.3)))(typescript@5.6.3): + dependencies: + bs-logger: 0.2.6 + ejs: 3.1.10 + fast-json-stable-stringify: 2.1.0 + jest: 29.7.0(@types/node@22.8.0)(ts-node@10.9.2(@types/node@22.8.0)(typescript@5.6.3)) + jest-util: 29.7.0 + json5: 2.2.3 + lodash.memoize: 4.1.2 + make-error: 1.3.6 + semver: 7.6.3 + typescript: 5.6.3 + yargs-parser: 21.1.1 + optionalDependencies: + '@babel/core': 7.26.0 + '@jest/transform': 29.7.0 + '@jest/types': 29.6.3 + babel-jest: 29.7.0(@babel/core@7.26.0) + ts-node@10.9.2(@types/node@22.8.0)(typescript@5.6.3): dependencies: '@cspotcode/source-map-support': 0.8.1 @@ -5195,6 +7265,8 @@ snapshots: dependencies: prelude-ls: 1.2.1 + type-detect@4.0.8: {} + type-fest@0.18.1: {} type-fest@0.20.2: {} @@ -5277,6 +7349,12 @@ snapshots: untildify@4.0.0: {} + update-browserslist-db@1.1.1(browserslist@4.24.2): + dependencies: + browserslist: 4.24.2 + escalade: 3.2.0 + picocolors: 1.1.1 + uri-js@4.4.1: dependencies: punycode: 2.3.1 @@ -5292,6 +7370,12 @@ snapshots: v8-compile-cache-lib@3.0.1: {} + v8-to-istanbul@9.3.0: + dependencies: + '@jridgewell/trace-mapping': 0.3.25 + '@types/istanbul-lib-coverage': 2.0.6 + convert-source-map: 2.0.0 + v8flags@4.0.1: {} validate-npm-package-license@3.0.4: @@ -5362,6 +7446,10 @@ snapshots: semver: 7.6.3 typescript: 5.6.3 + walker@1.0.8: + dependencies: + makeerror: 1.0.12 + webidl-conversions@3.0.1: {} whatwg-url@5.0.0: @@ -5408,12 +7496,16 @@ snapshots: yallist@2.1.2: {} + yallist@3.1.1: {} + yallist@4.0.0: {} yaml@2.6.0: {} yargs-parser@20.2.9: {} + yargs-parser@21.1.1: {} + yargs@16.2.0: dependencies: cliui: 7.0.4 @@ -5424,6 +7516,16 @@ snapshots: y18n: 5.0.8 yargs-parser: 20.2.9 + yargs@17.7.2: + dependencies: + cliui: 8.0.1 + escalade: 3.2.0 + get-caller-file: 2.0.5 + require-directory: 2.1.1 + string-width: 4.2.3 + y18n: 5.0.8 + yargs-parser: 21.1.1 + yn@3.1.1: {} yocto-queue@0.1.0: {} diff --git a/solana/bridge_token_factory/pnpm-workspace.yaml b/solana/bridge_token_factory/pnpm-workspace.yaml index bf8669bd..5cfadd14 100644 --- a/solana/bridge_token_factory/pnpm-workspace.yaml +++ b/solana/bridge_token_factory/pnpm-workspace.yaml @@ -1,3 +1,4 @@ packages: - "ts/sdk" - "ts/cli" + - "ts/tests" diff --git a/solana/bridge_token_factory/tests/Test.toml b/solana/bridge_token_factory/tests/Test.toml new file mode 100644 index 00000000..c18a254b --- /dev/null +++ b/solana/bridge_token_factory/tests/Test.toml @@ -0,0 +1,23 @@ +[test] +startup_wait = 20000 +shutdown_wait = 2000 +upgradeable = false + +[[test.genesis]] +address = "worm2ZoG2kUd4vFXhvjh93UUH596ayRfgQ2MgjNMTth" +program = "assets/common/wormhole.so" + +[[test.validator.account_dir]] +directory = "tests/assets/common" + +[[test.validator.account_dir]] +directory = "tests/assets/main" + +[[test.validator.account_dir]] +directory = "tests/assets/user/logMetadata/noMetadata" + +[[test.validator.account_dir]] +directory = "tests/assets/user/logMetadata/mplMetadata" + +[scripts] +test = "pnpm _test" \ No newline at end of file diff --git a/solana/bridge_token_factory/tests/assets/common/wormhole.so b/solana/bridge_token_factory/tests/assets/common/wormhole.so new file mode 100644 index 0000000000000000000000000000000000000000..ef0a0bd62469326e41165a9ff42198c8da208031 GIT binary patch literal 973360 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�eizx=-PzXe4p==1OQqdeJ!7^z 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ά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', 'Mint address') - .requiredOption('--nonce ', 'Nonce') + .command('finalize-transfer') + .description('Finalize transfer') + .option('--token ', 'Near token address') + .option('--mint ', 'Mint address') + .requiredOption('--destination-nonce ', 'Nonce') + .requiredOption('--origin-chain ', 'Origin chain') + .requiredOption('--origin-nonce ', 'Origin nonce') .requiredOption('--amount ', 'Amount') .option('--recipient ', 'Recipient') .option('--signature ', 'Signature') .action( async ({ + token, mint, - nonce, + destinationNonce, + originChain, + originNonce, amount, recipient, signature, }: { - mint: string; - nonce: string; + token?: string; + mint?: string; + destinationNonce: string; + originChain: string; + originNonce: string; amount: string; recipient?: string; signature?: string; }) => { const {sdk} = getContext(); - const mintPk = await parsePubkey(mint); + const mintPk = mint ? await parsePubkey(mint) : undefined; const recipientPk = recipient ? await parsePubkey(recipient) : sdk.provider.publicKey!; - const {instructions, signers} = await sdk.finalizeTransferNative({ + const {instructions, signers} = await sdk.finalizeTransfer({ mint: mintPk, - nonce: new BN(nonce), + token, + destinationNonce: new BN(destinationNonce), + transferId: { + originChain: parseInt(originChain), + originNonce: new BN(originNonce), + }, amount: new BN(amount), recipient: recipientPk, signature: signature ? JSON.parse(signature) : new Array(65).fill(0), diff --git a/solana/bridge_token_factory/ts/cli/src/finalizeTransferBridged.ts b/solana/bridge_token_factory/ts/cli/src/finalizeTransferBridged.ts deleted file mode 100644 index e45a1cca..00000000 --- a/solana/bridge_token_factory/ts/cli/src/finalizeTransferBridged.ts +++ /dev/null @@ -1,44 +0,0 @@ -import {Command} from 'commander'; -import {getContext} from './context'; -import {executeTx} from './executor'; -import BN from 'bn.js'; -import {parsePubkey} from './keyParser'; - -export function installFinalizeTransferBridgedCLI(program: Command) { - program - .command('finalize-transfer-bridged') - .description('Finalize bridged transfer') - .requiredOption('--token ', 'Near token address') - .requiredOption('--nonce ', 'Nonce') - .requiredOption('--amount ', 'Amount') - .option('--recipient ', 'Recipient') - .option('--signature ', 'Signature') - .action( - async ({ - token, - nonce, - amount, - recipient, - signature, - }: { - token: string; - nonce: string; - amount: string; - recipient?: string; - signature?: string; - }) => { - const {sdk} = getContext(); - const recipientPk = recipient - ? await parsePubkey(recipient) - : sdk.provider.publicKey!; - const {instructions, signers} = await sdk.finalizeTransferBridged({ - token, - nonce: new BN(nonce), - amount: new BN(amount), - recipient: recipientPk, - signature: signature ? JSON.parse(signature) : new Array(65).fill(0), - }); - await executeTx({instructions, signers}); - }, - ); -} diff --git a/solana/bridge_token_factory/ts/cli/src/initTransferNative.ts b/solana/bridge_token_factory/ts/cli/src/initTransfer.ts similarity index 53% rename from solana/bridge_token_factory/ts/cli/src/initTransferNative.ts rename to solana/bridge_token_factory/ts/cli/src/initTransfer.ts index eaf93c03..48c54454 100644 --- a/solana/bridge_token_factory/ts/cli/src/initTransferNative.ts +++ b/solana/bridge_token_factory/ts/cli/src/initTransfer.ts @@ -4,33 +4,41 @@ import {executeTx} from './executor'; import BN from 'bn.js'; import {parsePubkey} from './keyParser'; -export function installInitTransferNativeCLI(program: Command) { +export function installInitTransferCLI(program: Command) { program - .command('init-transfer-native') - .description('Init native transfer') - .requiredOption('--mint ', 'Mint address') + .command('init-transfer') + .description('Init transfer') + .option('--token ', 'Near token address') + .option('--mint ', 'Mint address') .requiredOption('--amount ', 'Amount') .requiredOption('--recipient
', 'Recipient') .option('--fee ', 'Fee', '0') + .option('--native-fee', 'Use native fee', '0') .action( async ({ + token, mint, amount, recipient, fee, + nativeFee, }: { - mint: string; + token?: string; + mint?: string; amount: string; recipient: string; - fee?: string; + fee: string; + nativeFee: string; }) => { const {sdk} = getContext(); - const mintPk = await parsePubkey(mint); - const {instructions, signers} = await sdk.initTransferNative({ + const mintPk = mint ? await parsePubkey(mint) : undefined; + const {instructions, signers} = await sdk.initTransfer({ mint: mintPk, + token, amount: new BN(amount), recipient, - fee: fee ? new BN(fee) : new BN(0), + fee: new BN(fee), + nativeFee: new BN(nativeFee), }); await executeTx({instructions, signers}); }, diff --git a/solana/bridge_token_factory/ts/cli/src/initTransferBridged.ts b/solana/bridge_token_factory/ts/cli/src/initTransferBridged.ts deleted file mode 100644 index f7c7fd7a..00000000 --- a/solana/bridge_token_factory/ts/cli/src/initTransferBridged.ts +++ /dev/null @@ -1,36 +0,0 @@ -import {Command} from 'commander'; -import {getContext} from './context'; -import {executeTx} from './executor'; -import BN from 'bn.js'; - -export function installInitTransferBridgedCLI(program: Command) { - program - .command('init-transfer-bridged') - .description('Init bridged transfer') - .requiredOption('--token ', 'Token address') - .requiredOption('--amount ', 'Amount') - .requiredOption('--recipient
', 'Recipient') - .option('--fee ', 'Fee', '0') - .action( - async ({ - token, - amount, - recipient, - fee, - }: { - token: string; - amount: string; - recipient: string; - fee?: string; - }) => { - const {sdk} = getContext(); - const {instructions, signers} = await sdk.initTransferBridged({ - token, - amount: new BN(amount), - recipient, - fee: fee ? new BN(fee) : new BN(0), - }); - await executeTx({instructions, signers}); - }, - ); -} diff --git a/solana/bridge_token_factory/ts/cli/src/logMetadata.ts b/solana/bridge_token_factory/ts/cli/src/logMetadata.ts new file mode 100644 index 00000000..916da4b2 --- /dev/null +++ b/solana/bridge_token_factory/ts/cli/src/logMetadata.ts @@ -0,0 +1,20 @@ +import {Command} from 'commander'; +import {getContext} from './context'; +import {executeTx} from './executor'; +import {parsePubkey} from './keyParser'; + +export function installLogMetadataCLI(program: Command) { + program + .command('log-metadata') + .description('Register a solana mint on near') + .requiredOption('--mint ', 'Mint address') + .action(async ({mint}: {mint: string}) => { + const {sdk} = getContext(); + const mintPk = await parsePubkey(mint); + + const {instructions, signers} = await sdk.logMetadata({ + mint: mintPk, + }); + await executeTx({instructions, signers}); + }); +} diff --git a/solana/bridge_token_factory/ts/cli/src/registerMint.ts b/solana/bridge_token_factory/ts/cli/src/registerMint.ts deleted file mode 100644 index 2ab0f2b8..00000000 --- a/solana/bridge_token_factory/ts/cli/src/registerMint.ts +++ /dev/null @@ -1,40 +0,0 @@ -import {Command} from 'commander'; -import {getContext} from './context'; -import {executeTx} from './executor'; -import {parsePubkey} from './keyParser'; - -export function installRegisterMintCLI(program: Command) { - program - .command('register-mint') - .description('Register a solana mint on near') - .requiredOption('--mint ', 'Mint address') - .option('--override-authority', 'Override mint authority') - .option('--name ', 'Override token name') - .option('--symbol ', 'Override token symbol') - .action( - async ({ - mint, - name, - symbol, - overrideAuthority, - }: { - mint: string; - name: string; - symbol: string; - overrideAuthority?: string; - }) => { - const {sdk} = getContext(); - const mintPk = await parsePubkey(mint); - const overrideAuthorityPk = overrideAuthority - ? await parsePubkey(overrideAuthority) - : null; - const {instructions, signers} = await sdk.registerMint({ - mint: mintPk, - name, - symbol, - overrideAuthority: overrideAuthorityPk, - }); - await executeTx({instructions, signers}); - }, - ); -} diff --git a/solana/bridge_token_factory/ts/sdk/src/bridge_token_factory.json b/solana/bridge_token_factory/ts/sdk/src/bridge_token_factory.json index 17f6a67a..5d7f7ade 100644 --- a/solana/bridge_token_factory/ts/sdk/src/bridge_token_factory.json +++ b/solana/bridge_token_factory/ts/sdk/src/bridge_token_factory.json @@ -346,16 +346,16 @@ ] }, { - "name": "finalize_transfer_bridged", + "name": "finalize_transfer", "discriminator": [ - 9, - 113, - 68, - 220, - 238, - 32, - 44, - 13 + 124, + 126, + 103, + 188, + 144, + 65, + 135, + 51 ], "accounts": [ { @@ -381,9 +381,6 @@ "name": "used_nonces", "writable": true }, - { - "name": "recipient" - }, { "name": "authority", "writable": true, @@ -407,8 +404,33 @@ } }, { - "name": "mint", - "writable": true + "name": "recipient" + }, + { + "name": "mint" + }, + { + "name": "vault", + "writable": true, + "optional": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 118, + 97, + 117, + 108, + 116 + ] + }, + { + "kind": "account", + "path": "mint" + } + ] + } }, { "name": "token_account", @@ -651,8 +673,7 @@ "address": "11111111111111111111111111111111" }, { - "name": "token_program", - "address": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" + "name": "token_program" } ], "args": [ @@ -677,16 +698,16 @@ ] }, { - "name": "finalize_transfer_native", + "name": "finalize_transfer_sol", "discriminator": [ + 104, 27, - 208, - 189, - 73, - 113, - 171, - 160, - 204 + 121, + 69, + 3, + 70, + 217, + 66 ], "accounts": [ { @@ -735,123 +756,31 @@ } }, { - "name": "recipient" - }, - { - "name": "mint" + "name": "recipient", + "writable": true }, { - "name": "vault", + "name": "sol_vault", "writable": true, "pda": { "seeds": [ { "kind": "const", "value": [ + 115, + 111, + 108, + 95, 118, 97, 117, 108, 116 ] - }, - { - "kind": "account", - "path": "mint" } ] } }, - { - "name": "token_account", - "writable": true, - "pda": { - "seeds": [ - { - "kind": "account", - "path": "recipient" - }, - { - "kind": "const", - "value": [ - 6, - 221, - 246, - 225, - 215, - 101, - 161, - 147, - 217, - 203, - 225, - 70, - 206, - 235, - 121, - 172, - 28, - 180, - 133, - 237, - 95, - 91, - 55, - 145, - 58, - 140, - 245, - 133, - 126, - 255, - 0, - 169 - ] - }, - { - "kind": "account", - "path": "mint" - } - ], - "program": { - "kind": "const", - "value": [ - 140, - 151, - 37, - 143, - 78, - 36, - 137, - 241, - 187, - 61, - 16, - 41, - 20, - 142, - 13, - 131, - 11, - 90, - 19, - 153, - 218, - 255, - 16, - 132, - 4, - 142, - 123, - 216, - 219, - 233, - 248, - 89 - ] - } - } - }, { "name": "wormhole", "accounts": [ @@ -994,16 +923,9 @@ } ] }, - { - "name": "associated_token_program", - "address": "ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL" - }, { "name": "system_program", "address": "11111111111111111111111111111111" - }, - { - "name": "token_program" } ], "args": [ @@ -1028,16 +950,16 @@ ] }, { - "name": "init_transfer_bridged", + "name": "init_transfer", "discriminator": [ - 102, - 4, - 222, - 127, - 222, - 254, - 91, - 156 + 174, + 50, + 134, + 99, + 122, + 243, + 243, + 224 ], "accounts": [ { @@ -1069,8 +991,54 @@ "name": "from", "writable": true }, + { + "name": "vault", + "writable": true, + "optional": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 118, + 97, + 117, + 108, + 116 + ] + }, + { + "kind": "account", + "path": "mint" + } + ] + } + }, + { + "name": "sol_vault", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 115, + 111, + 108, + 95, + 118, + 97, + 117, + 108, + 116 + ] + } + ] + } + }, { "name": "user", + "writable": true, "signer": true }, { @@ -1216,8 +1184,7 @@ ] }, { - "name": "token_program", - "address": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" + "name": "token_program" } ], "args": [ @@ -1232,16 +1199,16 @@ ] }, { - "name": "init_transfer_native", + "name": "init_transfer_sol", "discriminator": [ - 253, - 5, - 175, - 189, - 176, - 62, - 114, - 77 + 124, + 167, + 164, + 191, + 81, + 140, + 108, + 30 ], "accounts": [ { @@ -1266,36 +1233,30 @@ } }, { - "name": "mint" - }, - { - "name": "from", - "writable": true - }, - { - "name": "vault", + "name": "sol_vault", "writable": true, "pda": { "seeds": [ { "kind": "const", "value": [ + 115, + 111, + 108, + 95, 118, 97, 117, 108, 116 ] - }, - { - "kind": "account", - "path": "mint" } ] } }, { "name": "user", + "writable": true, "signer": true }, { @@ -1439,9 +1400,6 @@ "address": "11111111111111111111111111111111" } ] - }, - { - "name": "token_program" } ], "args": [ @@ -1509,6 +1467,28 @@ ] } }, + { + "name": "sol_vault", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 115, + 111, + 108, + 95, + 118, + 97, + 117, + 108, + 116 + ] + } + ] + } + }, { "name": "wormhole_bridge", "docs": [ @@ -1645,16 +1625,16 @@ ] }, { - "name": "register_mint", + "name": "log_metadata", "discriminator": [ - 242, - 43, - 74, - 162, - 217, - 214, - 191, - 171 + 168, + 157, + 195, + 79, + 96, + 210, + 208, + 2 ], "accounts": [ { @@ -1681,11 +1661,6 @@ { "name": "mint" }, - { - "name": "override_authority", - "signer": true, - "optional": true - }, { "name": "metadata", "optional": true @@ -1866,16 +1841,7 @@ "address": "ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL" } ], - "args": [ - { - "name": "metadata_override", - "type": { - "defined": { - "name": "MetadataOverride" - } - } - } - ] + "args": [] } ], "accounts": [ @@ -1919,19 +1885,28 @@ }, { "code": 6002, - "name": "NonceAlreadyUsed" + "name": "NonceAlreadyUsed", + "msg": "Nonce already used" }, { "code": 6003, - "name": "Unauthorized" + "name": "TokenMetadataNotProvided", + "msg": "Token metadata not provided" }, { "code": 6004, - "name": "TokenMetadataNotProvided" + "name": "InvalidTokenMetadataAddress", + "msg": "Invalid token metadata address" }, { "code": 6005, - "name": "SolanaTokenParsingFailed" + "name": "InvalidBridgedToken", + "msg": "Invalid bridged token" + }, + { + "code": 6006, + "name": "InvalidFee", + "msg": "Invalid fee" } ], "types": [ @@ -1946,7 +1921,7 @@ }, { "name": "max_used_nonce", - "type": "u128" + "type": "u64" }, { "name": "derived_near_bridge_address", @@ -1981,6 +1956,10 @@ "name": "authority", "type": "u8" }, + { + "name": "sol_vault", + "type": "u8" + }, { "name": "wormhole", "type": { @@ -2022,8 +2001,16 @@ "kind": "struct", "fields": [ { - "name": "nonce", - "type": "u128" + "name": "destination_nonce", + "type": "u64" + }, + { + "name": "transfer_id", + "type": { + "defined": { + "name": "TransferId" + } + } }, { "name": "amount", @@ -2054,22 +2041,10 @@ { "name": "fee", "type": "u128" - } - ] - } - }, - { - "name": "MetadataOverride", - "type": { - "kind": "struct", - "fields": [ - { - "name": "name", - "type": "string" }, { - "name": "symbol", - "type": "string" + "name": "native_fee", + "type": "u64" } ] } @@ -2103,6 +2078,22 @@ ] } }, + { + "name": "TransferId", + "type": { + "kind": "struct", + "fields": [ + { + "name": "origin_chain", + "type": "u8" + }, + { + "name": "origin_nonce", + "type": "u64" + } + ] + } + }, { "name": "UsedNonces", "serialization": "bytemuckunsafe", @@ -2151,6 +2142,11 @@ "type": "u8", "value": "2" }, + { + "name": "SOL_VAULT_SEED", + "type": "bytes", + "value": "[115, 111, 108, 95, 118, 97, 117, 108, 116]" + }, { "name": "USED_NONCES_ACCOUNT_SIZE", "type": "u32", diff --git a/solana/bridge_token_factory/ts/sdk/src/bridge_token_factory.ts b/solana/bridge_token_factory/ts/sdk/src/bridge_token_factory.ts index 48d027be..4016acee 100644 --- a/solana/bridge_token_factory/ts/sdk/src/bridge_token_factory.ts +++ b/solana/bridge_token_factory/ts/sdk/src/bridge_token_factory.ts @@ -352,16 +352,16 @@ export type BridgeTokenFactory = { ] }, { - "name": "finalizeTransferBridged", + "name": "finalizeTransfer", "discriminator": [ - 9, - 113, - 68, - 220, - 238, - 32, - 44, - 13 + 124, + 126, + 103, + 188, + 144, + 65, + 135, + 51 ], "accounts": [ { @@ -387,9 +387,6 @@ export type BridgeTokenFactory = { "name": "usedNonces", "writable": true }, - { - "name": "recipient" - }, { "name": "authority", "writable": true, @@ -413,8 +410,33 @@ export type BridgeTokenFactory = { } }, { - "name": "mint", - "writable": true + "name": "recipient" + }, + { + "name": "mint" + }, + { + "name": "vault", + "writable": true, + "optional": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 118, + 97, + 117, + 108, + 116 + ] + }, + { + "kind": "account", + "path": "mint" + } + ] + } }, { "name": "tokenAccount", @@ -657,8 +679,7 @@ export type BridgeTokenFactory = { "address": "11111111111111111111111111111111" }, { - "name": "tokenProgram", - "address": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" + "name": "tokenProgram" } ], "args": [ @@ -683,16 +704,16 @@ export type BridgeTokenFactory = { ] }, { - "name": "finalizeTransferNative", + "name": "finalizeTransferSol", "discriminator": [ + 104, 27, - 208, - 189, - 73, - 113, - 171, - 160, - 204 + 121, + 69, + 3, + 70, + 217, + 66 ], "accounts": [ { @@ -741,123 +762,31 @@ export type BridgeTokenFactory = { } }, { - "name": "recipient" - }, - { - "name": "mint" + "name": "recipient", + "writable": true }, { - "name": "vault", + "name": "solVault", "writable": true, "pda": { "seeds": [ { "kind": "const", "value": [ + 115, + 111, + 108, + 95, 118, 97, 117, 108, 116 ] - }, - { - "kind": "account", - "path": "mint" } ] } }, - { - "name": "tokenAccount", - "writable": true, - "pda": { - "seeds": [ - { - "kind": "account", - "path": "recipient" - }, - { - "kind": "const", - "value": [ - 6, - 221, - 246, - 225, - 215, - 101, - 161, - 147, - 217, - 203, - 225, - 70, - 206, - 235, - 121, - 172, - 28, - 180, - 133, - 237, - 95, - 91, - 55, - 145, - 58, - 140, - 245, - 133, - 126, - 255, - 0, - 169 - ] - }, - { - "kind": "account", - "path": "mint" - } - ], - "program": { - "kind": "const", - "value": [ - 140, - 151, - 37, - 143, - 78, - 36, - 137, - 241, - 187, - 61, - 16, - 41, - 20, - 142, - 13, - 131, - 11, - 90, - 19, - 153, - 218, - 255, - 16, - 132, - 4, - 142, - 123, - 216, - 219, - 233, - 248, - 89 - ] - } - } - }, { "name": "wormhole", "accounts": [ @@ -1000,16 +929,9 @@ export type BridgeTokenFactory = { } ] }, - { - "name": "associatedTokenProgram", - "address": "ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL" - }, { "name": "systemProgram", "address": "11111111111111111111111111111111" - }, - { - "name": "tokenProgram" } ], "args": [ @@ -1034,16 +956,16 @@ export type BridgeTokenFactory = { ] }, { - "name": "initTransferBridged", + "name": "initTransfer", "discriminator": [ - 102, - 4, - 222, - 127, - 222, - 254, - 91, - 156 + 174, + 50, + 134, + 99, + 122, + 243, + 243, + 224 ], "accounts": [ { @@ -1075,8 +997,54 @@ export type BridgeTokenFactory = { "name": "from", "writable": true }, + { + "name": "vault", + "writable": true, + "optional": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 118, + 97, + 117, + 108, + 116 + ] + }, + { + "kind": "account", + "path": "mint" + } + ] + } + }, + { + "name": "solVault", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 115, + 111, + 108, + 95, + 118, + 97, + 117, + 108, + 116 + ] + } + ] + } + }, { "name": "user", + "writable": true, "signer": true }, { @@ -1222,8 +1190,7 @@ export type BridgeTokenFactory = { ] }, { - "name": "tokenProgram", - "address": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" + "name": "tokenProgram" } ], "args": [ @@ -1238,16 +1205,16 @@ export type BridgeTokenFactory = { ] }, { - "name": "initTransferNative", + "name": "initTransferSol", "discriminator": [ - 253, - 5, - 175, - 189, - 176, - 62, - 114, - 77 + 124, + 167, + 164, + 191, + 81, + 140, + 108, + 30 ], "accounts": [ { @@ -1272,36 +1239,30 @@ export type BridgeTokenFactory = { } }, { - "name": "mint" - }, - { - "name": "from", - "writable": true - }, - { - "name": "vault", + "name": "solVault", "writable": true, "pda": { "seeds": [ { "kind": "const", "value": [ + 115, + 111, + 108, + 95, 118, 97, 117, 108, 116 ] - }, - { - "kind": "account", - "path": "mint" } ] } }, { "name": "user", + "writable": true, "signer": true }, { @@ -1445,9 +1406,6 @@ export type BridgeTokenFactory = { "address": "11111111111111111111111111111111" } ] - }, - { - "name": "tokenProgram" } ], "args": [ @@ -1515,6 +1473,28 @@ export type BridgeTokenFactory = { ] } }, + { + "name": "solVault", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 115, + 111, + 108, + 95, + 118, + 97, + 117, + 108, + 116 + ] + } + ] + } + }, { "name": "wormholeBridge", "docs": [ @@ -1651,16 +1631,16 @@ export type BridgeTokenFactory = { ] }, { - "name": "registerMint", + "name": "logMetadata", "discriminator": [ - 242, - 43, - 74, - 162, - 217, - 214, - 191, - 171 + 168, + 157, + 195, + 79, + 96, + 210, + 208, + 2 ], "accounts": [ { @@ -1687,11 +1667,6 @@ export type BridgeTokenFactory = { { "name": "mint" }, - { - "name": "overrideAuthority", - "signer": true, - "optional": true - }, { "name": "metadata", "optional": true @@ -1872,16 +1847,7 @@ export type BridgeTokenFactory = { "address": "ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL" } ], - "args": [ - { - "name": "metadataOverride", - "type": { - "defined": { - "name": "metadataOverride" - } - } - } - ] + "args": [] } ], "accounts": [ @@ -1925,19 +1891,28 @@ export type BridgeTokenFactory = { }, { "code": 6002, - "name": "nonceAlreadyUsed" + "name": "nonceAlreadyUsed", + "msg": "Nonce already used" }, { "code": 6003, - "name": "unauthorized" + "name": "tokenMetadataNotProvided", + "msg": "Token metadata not provided" }, { "code": 6004, - "name": "tokenMetadataNotProvided" + "name": "invalidTokenMetadataAddress", + "msg": "Invalid token metadata address" }, { "code": 6005, - "name": "solanaTokenParsingFailed" + "name": "invalidBridgedToken", + "msg": "Invalid bridged token" + }, + { + "code": 6006, + "name": "invalidFee", + "msg": "Invalid fee" } ], "types": [ @@ -1952,7 +1927,7 @@ export type BridgeTokenFactory = { }, { "name": "maxUsedNonce", - "type": "u128" + "type": "u64" }, { "name": "derivedNearBridgeAddress", @@ -1987,6 +1962,10 @@ export type BridgeTokenFactory = { "name": "authority", "type": "u8" }, + { + "name": "solVault", + "type": "u8" + }, { "name": "wormhole", "type": { @@ -2028,8 +2007,16 @@ export type BridgeTokenFactory = { "kind": "struct", "fields": [ { - "name": "nonce", - "type": "u128" + "name": "destinationNonce", + "type": "u64" + }, + { + "name": "transferId", + "type": { + "defined": { + "name": "transferId" + } + } }, { "name": "amount", @@ -2060,22 +2047,10 @@ export type BridgeTokenFactory = { { "name": "fee", "type": "u128" - } - ] - } - }, - { - "name": "metadataOverride", - "type": { - "kind": "struct", - "fields": [ - { - "name": "name", - "type": "string" }, { - "name": "symbol", - "type": "string" + "name": "nativeFee", + "type": "u64" } ] } @@ -2109,6 +2084,22 @@ export type BridgeTokenFactory = { ] } }, + { + "name": "transferId", + "type": { + "kind": "struct", + "fields": [ + { + "name": "originChain", + "type": "u8" + }, + { + "name": "originNonce", + "type": "u64" + } + ] + } + }, { "name": "usedNonces", "serialization": "bytemuckunsafe", @@ -2157,6 +2148,11 @@ export type BridgeTokenFactory = { "type": "u8", "value": "2" }, + { + "name": "solVaultSeed", + "type": "bytes", + "value": "[115, 111, 108, 95, 118, 97, 117, 108, 116]" + }, { "name": "usedNoncesAccountSize", "type": "u32", diff --git a/solana/bridge_token_factory/ts/sdk/src/index.ts b/solana/bridge_token_factory/ts/sdk/src/index.ts index 81d197e9..8d90353f 100644 --- a/solana/bridge_token_factory/ts/sdk/src/index.ts +++ b/solana/bridge_token_factory/ts/sdk/src/index.ts @@ -1,4 +1,4 @@ -import {IdlAccounts, Program, Provider} from '@coral-xyz/anchor'; +import {IdlAccounts, IdlTypes, Program, Provider} from '@coral-xyz/anchor'; import {BridgeTokenFactory} from './bridge_token_factory'; import * as BridgeTokenFactoryIdl from './bridge_token_factory.json'; @@ -26,6 +26,7 @@ export type TransactionData = { }; export type ConfigAccount = IdlAccounts['config']; +export type TransferId = IdlTypes['transferId']; const MPL_PROGRAM_ID = new PublicKey( 'metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s', @@ -50,6 +51,14 @@ export class OmniBridgeSolanaSDK { ), ); + public static readonly SOL_VAULT_SEED = Buffer.from( + JSON.parse( + BridgeTokenFactoryIdl.constants.find( + ({name}) => name === 'SOL_VAULT_SEED', + )!.value, + ), + ); + public static readonly VAULT_SEED = Buffer.from( JSON.parse( BridgeTokenFactoryIdl.constants.find(({name}) => name === 'VAULT_SEED')! @@ -93,6 +102,13 @@ export class OmniBridgeSolanaSDK { ); } + solVault(): [PublicKey, number] { + return PublicKey.findProgramAddressSync( + [OmniBridgeSolanaSDK.SOL_VAULT_SEED], + this.programId, + ); + } + wormholeBridgeId(): [PublicKey, number] { return PublicKey.findProgramAddressSync( [Buffer.from('Bridge', 'utf-8')], @@ -142,16 +158,22 @@ export class OmniBridgeSolanaSDK { constructor({ provider, + programId, wormholeProgramId, }: { provider: Provider; + programId?: PublicKey; wormholeProgramId: PublicKey; }) { this.wormholeProgramId = wormholeProgramId; - this.program = new Program( - BridgeTokenFactoryIdl as BridgeTokenFactory, - provider, - ); + let idl = BridgeTokenFactoryIdl; + if (programId) { + idl = { + ...BridgeTokenFactoryIdl, + address: programId.toBase58(), + }; + } + this.program = new Program(idl as BridgeTokenFactory, provider); } get programId(): PublicKey { @@ -181,13 +203,14 @@ export class OmniBridgeSolanaSDK { payer?: PublicKey; nearBridge: number[]; admin?: PublicKey; - }): Promise { + }): Promise { const wormholeMessage = Keypair.generate(); const instruction = await this.program.methods .initialize(admin || this.provider.publicKey!, nearBridge) .accountsStrict({ config: this.configId()[0], authority: this.authority()[0], + solVault: this.solVault()[0], payer: payer || this.provider.publicKey!, clock: SYSVAR_CLOCK_PUBKEY, rent: SYSVAR_RENT_PUBKEY, @@ -200,7 +223,11 @@ export class OmniBridgeSolanaSDK { program: this.programId, }) .instruction(); - return {instructions: [instruction], signers: [wormholeMessage]}; + return { + instructions: [instruction], + signers: [wormholeMessage], + message: wormholeMessage.publicKey, + }; } async deployToken({ @@ -219,7 +246,7 @@ export class OmniBridgeSolanaSDK { signature: number[]; payer?: PublicKey; sequenceNumber?: BN; - }): Promise { + }): Promise { const wormholeMessage = Keypair.generate(); const [mint] = this.wrappedMintId({token}); const [metadata] = PublicKey.findProgramAddressSync( @@ -266,161 +293,26 @@ export class OmniBridgeSolanaSDK { }) .instruction(); - return {instructions: [instruction], signers: [wormholeMessage]}; - } - - async finalizeTransferBridged({ - nonce, - token, - amount, - recipient, - feeRecipient = null, - signature, - payer, - sequenceNumber, - }: { - nonce: BN; - token: string; - amount: BN; - recipient: PublicKey; - feeRecipient?: string | null; - signature: number[]; - payer?: PublicKey; - sequenceNumber?: BN; - }): Promise { - const wormholeMessage = Keypair.generate(); - - if (!sequenceNumber) { - sequenceNumber = await this.fetchNextSequenceNumber(); - } - - const [config] = this.configId(); - const [usedNonces] = this.usedNoncesId({nonce}); - const [mint] = this.wrappedMintId({token}); - const tokenAccount = getAssociatedTokenAddressSync(mint, recipient, true); - - const instruction = await this.program.methods - .finalizeTransferBridged({ - payload: { - nonce, - token, - amount, - feeRecipient, - }, - signature, - }) - .accountsStrict({ - config, - usedNonces, - wormhole: { - config, - bridge: this.wormholeBridgeId()[0], - feeCollector: this.wormholeFeeCollectorId()[0], - sequence: this.wormholeSequenceId()[0], - clock: SYSVAR_CLOCK_PUBKEY, - rent: SYSVAR_RENT_PUBKEY, - systemProgram: SystemProgram.programId, - wormholeProgram: this.wormholeProgramId, - message: wormholeMessage.publicKey, - payer: payer || this.provider.publicKey!, - }, - recipient, - authority: this.authority()[0], - mint, - systemProgram: SystemProgram.programId, - tokenProgram: TOKEN_PROGRAM_ID, - tokenAccount, - associatedTokenProgram: ASSOCIATED_TOKEN_PROGRAM_ID, - }) - .instruction(); - - return {instructions: [instruction], signers: [wormholeMessage]}; - } - - async initTransferBridged({ - token, - from, - user, - amount, - recipient, - fee, - payer, - sequenceNumber, - }: { - token: string; - from?: PublicKey; - user?: PublicKey; - amount: BN; - recipient: string; - fee: BN; - payer?: PublicKey; - sequenceNumber?: BN; - }): Promise { - const wormholeMessage = Keypair.generate(); - const [config] = this.configId(); - const [mint] = this.wrappedMintId({token}); - - if (!sequenceNumber) { - sequenceNumber = await this.fetchNextSequenceNumber(); - } - - if (!user) { - user = this.provider.publicKey!; - } - - if (!from) { - from = getAssociatedTokenAddressSync(mint, user, true); - } - - const instruction = await this.program.methods - .initTransferBridged({ - amount, - recipient, - fee, - }) - .accountsStrict({ - wormhole: { - config, - bridge: this.wormholeBridgeId()[0], - feeCollector: this.wormholeFeeCollectorId()[0], - sequence: this.wormholeSequenceId()[0], - clock: SYSVAR_CLOCK_PUBKEY, - rent: SYSVAR_RENT_PUBKEY, - systemProgram: SystemProgram.programId, - wormholeProgram: this.wormholeProgramId, - message: wormholeMessage.publicKey, - payer: payer || this.provider.publicKey!, - }, - authority: this.authority()[0], - mint, - tokenProgram: TOKEN_PROGRAM_ID, - from, - user, - }) - .instruction(); - - return {instructions: [instruction], signers: [wormholeMessage]}; + return { + instructions: [instruction], + signers: [wormholeMessage], + message: wormholeMessage.publicKey, + }; } - async registerMint({ + async logMetadata({ mint, - name = '', - symbol = '', sequenceNumber, - overrideAuthority = null, useMetaplex, payer, token22, }: { mint: PublicKey; - name?: string; - symbol?: string; sequenceNumber?: BN; - overrideAuthority?: PublicKey | null; useMetaplex?: boolean; payer?: PublicKey; token22?: boolean; - }): Promise { + }): Promise { const wormholeMessage = Keypair.generate(); const [config] = this.configId(); const [metadata] = PublicKey.findProgramAddressSync( @@ -441,12 +333,12 @@ export class OmniBridgeSolanaSDK { token22 = mintInfo?.owner.equals(TOKEN_2022_PROGRAM_ID); } - if (useMetaplex === undefined && !overrideAuthority && !token22) { + if (useMetaplex === undefined && !token22) { useMetaplex = true; } const instruction = await this.program.methods - .registerMint({name, symbol}) + .logMetadata() .accountsStrict({ authority: this.authority()[0], mint, @@ -465,18 +357,23 @@ export class OmniBridgeSolanaSDK { metadata: useMetaplex ? metadata : null, systemProgram: SystemProgram.programId, tokenProgram: token22 ? TOKEN_2022_PROGRAM_ID : TOKEN_PROGRAM_ID, - overrideAuthority, vault: this.vaultId({mint})[0], associatedTokenProgram: ASSOCIATED_TOKEN_PROGRAM_ID, }) .instruction(); - return {instructions: [instruction], signers: [wormholeMessage]}; + return { + instructions: [instruction], + signers: [wormholeMessage], + message: wormholeMessage.publicKey, + }; } - async finalizeTransferNative({ - nonce, + async finalizeTransfer({ + destinationNonce, + transferId, mint, + token, amount, recipient, feeRecipient = null, @@ -485,8 +382,10 @@ export class OmniBridgeSolanaSDK { sequenceNumber, token22, }: { - nonce: BN; - mint: PublicKey; + destinationNonce: BN; + transferId: TransferId; + mint?: PublicKey; + token?: string; amount: BN; recipient: PublicKey; feeRecipient?: string | null; @@ -494,15 +393,24 @@ export class OmniBridgeSolanaSDK { payer?: PublicKey; sequenceNumber?: BN; token22?: boolean; - }): Promise { + }): Promise { const wormholeMessage = Keypair.generate(); + if (!mint) { + if (!token) { + throw new Error('One of token/mint must be supplied'); + } + mint = this.wrappedMintId({token})[0]; + } + + const vault = token ? null : this.vaultId({mint})[0]; + if (!sequenceNumber) { sequenceNumber = await this.fetchNextSequenceNumber(); } const [config] = this.configId(); - const [usedNonces] = this.usedNoncesId({nonce}); + const [usedNonces] = this.usedNoncesId({nonce: destinationNonce}); if (token22 === undefined) { const mintInfo = await this.provider.connection.getAccountInfo(mint); @@ -517,9 +425,10 @@ export class OmniBridgeSolanaSDK { ); const instruction = await this.program.methods - .finalizeTransferNative({ + .finalizeTransfer({ payload: { - nonce, + destinationNonce, + transferId, amount, feeRecipient, }, @@ -543,7 +452,7 @@ export class OmniBridgeSolanaSDK { }, recipient, mint, - vault: this.vaultId({mint})[0], + vault, systemProgram: SystemProgram.programId, tokenProgram: token22 ? TOKEN_2022_PROGRAM_ID : TOKEN_PROGRAM_ID, associatedTokenProgram: ASSOCIATED_TOKEN_PROGRAM_ID, @@ -551,31 +460,49 @@ export class OmniBridgeSolanaSDK { }) .instruction(); - return {instructions: [instruction], signers: [wormholeMessage]}; + return { + instructions: [instruction], + signers: [wormholeMessage], + message: wormholeMessage.publicKey, + }; } - async initTransferNative({ + async initTransfer({ mint, + token, from, user, amount, recipient, fee, + nativeFee, payer, sequenceNumber, token22, }: { - mint: PublicKey; + mint?: PublicKey; + token?: string; from?: PublicKey; user?: PublicKey; amount: BN; recipient: string; fee: BN; + nativeFee: BN; payer?: PublicKey; sequenceNumber?: BN; token22?: boolean; - }): Promise { + }): Promise { const wormholeMessage = Keypair.generate(); + + if (!mint) { + if (!token) { + throw new Error('One of token/mint must be supplied'); + } + mint = this.wrappedMintId({token})[0]; + } + + const vault = token ? null : this.vaultId({mint})[0]; + const [config] = this.configId(); if (!sequenceNumber) { @@ -601,9 +528,10 @@ export class OmniBridgeSolanaSDK { } const instruction = await this.program.methods - .initTransferNative({ + .initTransfer({ amount, recipient, + nativeFee, fee, }) .accountsStrict({ @@ -620,14 +548,143 @@ export class OmniBridgeSolanaSDK { payer: payer || this.provider.publicKey!, }, authority: this.authority()[0], + solVault: this.solVault()[0], mint, tokenProgram: token22 ? TOKEN_2022_PROGRAM_ID : TOKEN_PROGRAM_ID, from, user, - vault: this.vaultId({mint})[0], + vault, + }) + .instruction(); + + return { + instructions: [instruction], + signers: [wormholeMessage], + message: wormholeMessage.publicKey, + }; + } + + async initTransferSol({ + user, + amount, + recipient, + nativeFee, + payer, + sequenceNumber, + }: { + user?: PublicKey; + amount: BN; + recipient: string; + nativeFee: BN; + payer?: PublicKey; + sequenceNumber?: BN; + }): Promise { + const wormholeMessage = Keypair.generate(); + const [config] = this.configId(); + + if (!sequenceNumber) { + sequenceNumber = await this.fetchNextSequenceNumber(); + } + + if (!user) { + user = this.provider.publicKey!; + } + + const instruction = await this.program.methods + .initTransferSol({ + amount, + recipient, + fee: new BN(0), + nativeFee, + }) + .accountsStrict({ + user, + authority: this.authority()[0], + solVault: this.solVault()[0], + wormhole: { + config, + bridge: this.wormholeBridgeId()[0], + feeCollector: this.wormholeFeeCollectorId()[0], + sequence: this.wormholeSequenceId()[0], + clock: SYSVAR_CLOCK_PUBKEY, + rent: SYSVAR_RENT_PUBKEY, + systemProgram: SystemProgram.programId, + wormholeProgram: this.wormholeProgramId, + message: wormholeMessage.publicKey, + payer: payer || this.provider.publicKey!, + }, + }) + .instruction(); + + return { + instructions: [instruction], + signers: [wormholeMessage], + message: wormholeMessage.publicKey, + }; + } + + async finalizeTransferSol({ + destinationNonce, + transferId, + amount, + recipient, + feeRecipient = null, + signature, + payer, + sequenceNumber, + }: { + destinationNonce: BN; + transferId: TransferId; + amount: BN; + recipient: PublicKey; + feeRecipient?: string | null; + signature: number[]; + payer?: PublicKey; + sequenceNumber?: BN; + }): Promise { + const wormholeMessage = Keypair.generate(); + const [config] = this.configId(); + + if (!sequenceNumber) { + sequenceNumber = await this.fetchNextSequenceNumber(); + } + + const instruction = await this.program.methods + .finalizeTransferSol({ + payload: { + destinationNonce, + transferId, + amount, + feeRecipient, + }, + signature, + }) + .accountsStrict({ + config, + usedNonces: this.usedNoncesId({nonce: destinationNonce})[0], + authority: this.authority()[0], + solVault: this.solVault()[0], + wormhole: { + config, + bridge: this.wormholeBridgeId()[0], + feeCollector: this.wormholeFeeCollectorId()[0], + sequence: this.wormholeSequenceId()[0], + clock: SYSVAR_CLOCK_PUBKEY, + rent: SYSVAR_RENT_PUBKEY, + systemProgram: SystemProgram.programId, + wormholeProgram: this.wormholeProgramId, + message: wormholeMessage.publicKey, + payer: payer || this.provider.publicKey!, + }, + recipient, + systemProgram: SystemProgram.programId, }) .instruction(); - return {instructions: [instruction], signers: [wormholeMessage]}; + return { + instructions: [instruction], + signers: [wormholeMessage], + message: wormholeMessage.publicKey, + }; } } diff --git a/solana/bridge_token_factory/ts/tests/.editorconfig b/solana/bridge_token_factory/ts/tests/.editorconfig new file mode 100644 index 00000000..79fe8026 --- /dev/null +++ b/solana/bridge_token_factory/ts/tests/.editorconfig @@ -0,0 +1,8 @@ +root = true + +[*] +indent_style = space +indent_size = 2 +end_of_line = lf +charset = utf-8 +insert_final_newline = true diff --git a/solana/bridge_token_factory/ts/tests/.eslintignore b/solana/bridge_token_factory/ts/tests/.eslintignore new file mode 100644 index 00000000..567609b1 --- /dev/null +++ b/solana/bridge_token_factory/ts/tests/.eslintignore @@ -0,0 +1 @@ +build/ diff --git a/solana/bridge_token_factory/ts/tests/.eslintrc.json b/solana/bridge_token_factory/ts/tests/.eslintrc.json new file mode 100644 index 00000000..f95bb333 --- /dev/null +++ b/solana/bridge_token_factory/ts/tests/.eslintrc.json @@ -0,0 +1,3 @@ +{ + "extends": "./node_modules/gts/" +} diff --git a/solana/bridge_token_factory/ts/tests/.prettierrc.js b/solana/bridge_token_factory/ts/tests/.prettierrc.js new file mode 100644 index 00000000..ff154833 --- /dev/null +++ b/solana/bridge_token_factory/ts/tests/.prettierrc.js @@ -0,0 +1,3 @@ +module.exports = { + ...require('gts/.prettierrc.json') +} diff --git a/solana/bridge_token_factory/ts/tests/__tests__/admin/initialize.spec.ts b/solana/bridge_token_factory/ts/tests/__tests__/admin/initialize.spec.ts new file mode 100644 index 00000000..247fb209 --- /dev/null +++ b/solana/bridge_token_factory/ts/tests/__tests__/admin/initialize.spec.ts @@ -0,0 +1,49 @@ +import {AnchorProvider, setProvider} from '@coral-xyz/anchor'; +import {PublicKey, Transaction} from '@solana/web3.js'; +import {OmniBridgeSolanaSDK} from 'omni-bridge-solana-sdk'; +import * as data from '../../src/data/admin/initialize'; +import {programIdKp} from '../../src/data'; +import {BN} from 'bn.js'; + +describe('initialize', () => { + let sdk: OmniBridgeSolanaSDK; + + beforeAll(() => { + sdk = new OmniBridgeSolanaSDK({ + provider: AnchorProvider.local(), + wormholeProgramId: new PublicKey( + 'worm2ZoG2kUd4vFXhvjh93UUH596ayRfgQ2MgjNMTth', + ), + }); + }); + + it('Initializes in the simple case', async () => { + const {nearBridge, admin} = data.simple; + const tx = new Transaction(); + const {instructions, signers} = await sdk.initialize({ + nearBridge: nearBridge, + admin, + }); + tx.add(...instructions); + + await expect( + sdk.provider.sendAndConfirm!(tx, [...signers, programIdKp]), + ).resolves.toBeTruthy(); + + await expect(sdk.fetchConfig()).resolves.toStrictEqual({ + admin, + maxUsedNonce: new BN(0), + derivedNearBridgeAddress: nearBridge, + bumps: { + config: sdk.configId()[1], + authority: sdk.authority()[1], + solVault: sdk.solVault()[1], + wormhole: { + bridge: sdk.wormholeBridgeId()[1], + feeCollector: sdk.wormholeFeeCollectorId()[1], + sequence: sdk.wormholeSequenceId()[1], + }, + }, + }); + }); +}); diff --git a/solana/bridge_token_factory/ts/tests/__tests__/user/logMetadata.spec.ts b/solana/bridge_token_factory/ts/tests/__tests__/user/logMetadata.spec.ts new file mode 100644 index 00000000..ef76275a --- /dev/null +++ b/solana/bridge_token_factory/ts/tests/__tests__/user/logMetadata.spec.ts @@ -0,0 +1,116 @@ +import {AnchorProvider} from '@coral-xyz/anchor'; +import {PublicKey, Transaction} from '@solana/web3.js'; +import {OmniBridgeSolanaSDK} from 'omni-bridge-solana-sdk'; +import * as data from '../../src/data/user/logMetadata'; + +describe('logMetadata', () => { + let sdk: OmniBridgeSolanaSDK; + + beforeAll(() => { + sdk = new OmniBridgeSolanaSDK({ + provider: AnchorProvider.local(), + wormholeProgramId: new PublicKey( + 'worm2ZoG2kUd4vFXhvjh93UUH596ayRfgQ2MgjNMTth', + ), + }); + }); + + it('Logs empty strings if no MPL account exists', async () => { + const {mint} = data.noMetadata; + const tx = new Transaction(); + const {instructions, signers, message} = await sdk.logMetadata({ + mint: mint.mint, + }); + tx.add(...instructions); + + await expect( + sdk.provider.sendAndConfirm!(tx, [...signers]), + ).resolves.toBeTruthy(); + const messageData = Buffer.alloc(43); + messageData.writeInt8(3, 0); // LogMetadata + messageData.writeInt8(2, 1); // SOLANA_OMNI_BRIDGE_CHAIN_ID + mint.mint.toBuffer().copy(messageData, 2); // mint + // Name + messageData.writeUint32LE(0, 34); + // Symbol + messageData.writeUint32LE(0, 38); + messageData.writeInt8(mint.decimals, 42); // Decimals + await expect( + sdk.provider.connection + .getAccountInfo(message) + .then(({data}) => data.subarray(95)), + ).resolves.toStrictEqual(messageData); + + await expect( + sdk.provider.connection + .getParsedAccountInfo(sdk.vaultId({mint: mint.mint})[0]) + // eslint-disable-next-line @typescript-eslint/no-explicit-any + .then(({value}) => (value.data as any).parsed.info), + ).resolves.toStrictEqual({ + isNative: false, + mint: mint.mint.toBase58(), + owner: sdk.authority()[0].toBase58(), + state: 'initialized', + tokenAmount: { + amount: '0', + decimals: mint.decimals, + uiAmount: 0, + uiAmountString: '0', + }, + }); + }); + + it('Logs MLP metadata', async () => { + const {mint, metadata} = data.mplMetadata; + const tx = new Transaction(); + const {instructions, signers, message} = await sdk.logMetadata({ + mint: mint.mint, + }); + tx.add(...instructions); + + await expect( + sdk.provider.sendAndConfirm!(tx, [...signers]), + ).resolves.toBeTruthy(); + const messageData = Buffer.alloc( + 43 + metadata.name.length + metadata.symbol.length, + ); + messageData.writeInt8(3, 0); // LogMetadata + messageData.writeInt8(2, 1); // SOLANA_OMNI_BRIDGE_CHAIN_ID + mint.mint.toBuffer().copy(messageData, 2); // mint + let offset = 34; + // Name + messageData.writeUint32LE(metadata.name.length, offset); + offset += 4; + messageData.write(metadata.name, offset); + offset += metadata.name.length; + // Symbol + messageData.writeUint32LE(metadata.symbol.length, offset); + offset += 4; + messageData.write(metadata.symbol, offset); + offset += metadata.symbol.length; + messageData.writeInt8(mint.decimals, offset); // Decimals + await expect( + sdk.provider.connection + .getAccountInfo(message) + .then(({data}) => data.subarray(95)), + ).resolves.toStrictEqual(messageData); + + await expect( + sdk.provider.connection + .getParsedAccountInfo(sdk.vaultId({mint: mint.mint})[0]) + // eslint-disable-next-line @typescript-eslint/no-explicit-any + .then(({value}) => (value.data as any).parsed.info), + ).resolves.toStrictEqual({ + isNative: false, + mint: mint.mint.toBase58(), + owner: sdk.authority()[0].toBase58(), + state: 'initialized', + tokenAmount: { + amount: '0', + decimals: mint.decimals, + uiAmount: 0, + uiAmountString: '0', + }, + }); + }); +}); diff --git a/solana/bridge_token_factory/ts/tests/jest.config.cjs b/solana/bridge_token_factory/ts/tests/jest.config.cjs new file mode 100644 index 00000000..df36dc04 --- /dev/null +++ b/solana/bridge_token_factory/ts/tests/jest.config.cjs @@ -0,0 +1,7 @@ +/** @type {import('ts-jest').JestConfigWithTsJest} */ +module.exports = { + preset: 'ts-jest', + testEnvironment: 'node', + testTimeout: 200000, + setupFilesAfterEnv: ['/src/jestSetup.ts'], +}; diff --git a/solana/bridge_token_factory/ts/tests/package-lock.json b/solana/bridge_token_factory/ts/tests/package-lock.json new file mode 100644 index 00000000..02396c85 --- /dev/null +++ b/solana/bridge_token_factory/ts/tests/package-lock.json @@ -0,0 +1,108 @@ +{ + "name": "omni-bridge-solana-tests", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "omni-bridge-solana-tests", + "version": "1.0.0", + "license": "ISC", + "devDependencies": { + "@types/node": "^22.7.5", + "gts": "^6.0.2", + "typescript": "^5.6.3" + } + }, + "../../node_modules/.pnpm/gts@6.0.2_typescript@5.6.3/node_modules/gts": { + "version": "6.0.2", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@typescript-eslint/eslint-plugin": "5.62.0", + "@typescript-eslint/parser": "5.62.0", + "chalk": "^4.1.2", + "eslint": "8.57.1", + "eslint-config-prettier": "9.1.0", + "eslint-plugin-n": "15.7.0", + "eslint-plugin-prettier": "5.2.1", + "execa": "^5.0.0", + "inquirer": "^7.3.3", + "json5": "^2.1.3", + "meow": "^9.0.0", + "ncp": "^2.0.0", + "prettier": "3.3.3", + "rimraf": "3.0.2", + "write-file-atomic": "^4.0.0" + }, + "bin": { + "gts": "build/src/cli.js" + }, + "devDependencies": { + "@npm/types": "^2.0.0", + "@types/cross-spawn": "^6.0.2", + "@types/eslint": "^8.0.0", + "@types/fs-extra": "^11.0.0", + "@types/inquirer": "^8.0.0", + "@types/json5": "2.2.0", + "@types/mocha": "^10.0.0", + "@types/ncp": "^2.0.4", + "@types/node": "^22.7.5", + "@types/rimraf": "^3.0.0", + "@types/sinon": "^17.0.0", + "@types/tmp": "^0.2.0", + "@types/write-file-atomic": "^4.0.0", + "c8": "^10.1.2", + "cross-spawn": "^7.0.3", + "fs-extra": "^11.0.0", + "inline-fixtures": "^1.1.0", + "js-green-licenses": "^4.0.0", + "mocha": "^10.0.0", + "sinon": "^19.0.0", + "tmp": "0.2.3", + "typescript": "^5.6.3" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "typescript": ">=5" + } + }, + "node_modules/@types/node": { + "version": "22.9.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.9.0.tgz", + "integrity": "sha512-vuyHg81vvWA1Z1ELfvLko2c8f34gyA0zaic0+Rllc5lbCnbSyuvb2Oxpm6TAUAC/2xZN3QGqxBNggD1nNR2AfQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "undici-types": "~6.19.8" + } + }, + "node_modules/gts": { + "resolved": "../../node_modules/.pnpm/gts@6.0.2_typescript@5.6.3/node_modules/gts", + "link": true + }, + "node_modules/typescript": { + "version": "5.6.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.3.tgz", + "integrity": "sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/undici-types": { + "version": "6.19.8", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz", + "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==", + "dev": true, + "license": "MIT" + } + } +} diff --git a/solana/bridge_token_factory/ts/tests/package.json b/solana/bridge_token_factory/ts/tests/package.json new file mode 100644 index 00000000..100b27fa --- /dev/null +++ b/solana/bridge_token_factory/ts/tests/package.json @@ -0,0 +1,41 @@ +{ + "name": "omni-bridge-solana-tests", + "version": "1.0.0", + "description": "", + "main": "index.js", + "scripts": { + "test-initialize-simple": "jest -t 'Initializes in the simple case'", + "test": "jest -t logMetadata", + "lint": "gts lint", + "clean": "gts clean", + "compile": "tsc", + "fix": "gts fix", + "setup-test": "ts-node src/main.ts" + }, + "keywords": [], + "author": "", + "license": "ISC", + "devDependencies": { + "@jest/globals": "^29.7.0", + "@types/bn.js": "^5.1.6", + "@types/jest": "^29.5.14", + "@types/node": "^22.7.5", + "gts": "^6.0.2", + "jest": "^29.7.0", + "ts-jest": "^29.2.5", + "ts-node": "^10.9.2", + "typescript": "^5.6.3" + }, + "dependencies": { + "@coral-xyz/anchor": "^0.30.1", + "@metaplex-foundation/mpl-token-metadata": "^3.3.0", + "@metaplex-foundation/umi": "^0.9.2", + "@metaplex-foundation/umi-bundle-defaults": "^0.9.2", + "@metaplex-foundation/umi-public-keys": "^0.8.9", + "@solana/spl-token": "^0.4.9", + "@solana/web3.js": "^1.95.4", + "bn.js": "^5.2.1", + "js-base64": "^3.7.7", + "omni-bridge-solana-sdk": "workspace:*" + } +} diff --git a/solana/bridge_token_factory/ts/tests/src/data/admin/index.ts b/solana/bridge_token_factory/ts/tests/src/data/admin/index.ts new file mode 100644 index 00000000..103b0e3a --- /dev/null +++ b/solana/bridge_token_factory/ts/tests/src/data/admin/index.ts @@ -0,0 +1,3 @@ +import * as initialize from './initialize'; + +export {initialize}; diff --git a/solana/bridge_token_factory/ts/tests/src/data/admin/initialize/index.ts b/solana/bridge_token_factory/ts/tests/src/data/admin/initialize/index.ts new file mode 100644 index 00000000..9c5542af --- /dev/null +++ b/solana/bridge_token_factory/ts/tests/src/data/admin/initialize/index.ts @@ -0,0 +1,3 @@ +import * as simple from './simple'; + +export {simple}; diff --git a/solana/bridge_token_factory/ts/tests/src/data/admin/initialize/simple.ts b/solana/bridge_token_factory/ts/tests/src/data/admin/initialize/simple.ts new file mode 100644 index 00000000..c07205ec --- /dev/null +++ b/solana/bridge_token_factory/ts/tests/src/data/admin/initialize/simple.ts @@ -0,0 +1,12 @@ +import {Keypair, PublicKey} from '@solana/web3.js'; + +export const admin = new PublicKey( + 'DAX51vquUE53GZs6QDkP8Rq3tw2UZsSCRhXwr6PEqbUG', +); + +export const nearBridge = [ + 28, 17, 25, 180, 48, 54, 234, 137, 49, 110, 21, 118, 154, 53, 146, 240, 156, + 214, 8, 185, 51, 198, 177, 189, 173, 80, 94, 221, 126, 144, 191, 244, 76, 81, + 113, 127, 120, 190, 78, 175, 100, 231, 82, 193, 67, 131, 161, 235, 103, 84, + 24, 157, 178, 232, 187, 79, 174, 254, 13, 2, 152, 121, 37, 104, +]; diff --git a/solana/bridge_token_factory/ts/tests/src/data/common.ts b/solana/bridge_token_factory/ts/tests/src/data/common.ts new file mode 100644 index 00000000..40ea3169 --- /dev/null +++ b/solana/bridge_token_factory/ts/tests/src/data/common.ts @@ -0,0 +1,126 @@ +/* eslint-disable n/no-unsupported-features/es-builtins */ +import {Keypair, PublicKey} from '@solana/web3.js'; +import BN from 'bn.js'; +import {OmniBridgeSolanaSDK} from 'omni-bridge-solana-sdk'; +import {Base64} from 'js-base64'; +import {MintLayout, TOKEN_PROGRAM_ID} from '@solana/spl-token'; +import { + findMetadataPda, + getMetadataAccountDataSerializer, + MetadataAccountDataArgs, + MPL_TOKEN_METADATA_PROGRAM_ID, +} from '@metaplex-foundation/mpl-token-metadata'; +import {Umi} from '@metaplex-foundation/umi'; + +BN.prototype.toJSON = function () { + return this.toString(); +}; + +const ACCOUNT_STORAGE_OVERHEAD = 128; +const DEFAULT_LAMPORTS_PER_BYTE_YEAR = Math.floor( + ((1_000_000_000 / 100) * 365) / (1024 * 1024), +); +const DEFAULT_EXEMPTION_THRESHOLD = 2.0; + +export function getMinimumBalanceForRentExemption(bytes: number) { + return ( + (ACCOUNT_STORAGE_OVERHEAD + bytes) * + DEFAULT_LAMPORTS_PER_BYTE_YEAR * + DEFAULT_EXEMPTION_THRESHOLD + ); +} + +export const programIdKp = Keypair.fromSecretKey( + Uint8Array.from([ + 225, 34, 97, 224, 178, 48, 236, 237, 241, 233, 132, 211, 119, 49, 88, 177, + 166, 27, 217, 184, 217, 106, 155, 103, 153, 230, 150, 210, 195, 72, 9, 57, + 38, 35, 227, 206, 5, 147, 218, 190, 207, 202, 141, 133, 60, 31, 98, 56, 108, + 157, 32, 138, 168, 136, 244, 155, 16, 157, 174, 238, 124, 95, 238, 37, + ]), +); // 3ZtEZ8xABFbUr4c1FVpXbQiVdqv4vwhvfCc8HMmhEeua + +export async function omniBridgeAccount({ + sdk, + account, + accountType, +}: { + sdk: OmniBridgeSolanaSDK; + account: T; + accountType: string; +}) { + const data = await sdk.program.coder.accounts.encode(accountType, account); + return { + pubkey: sdk.configId()[0].toBase58(), + account: { + lamports: getMinimumBalanceForRentExemption(data.length), + data: [Base64.fromUint8Array(data), 'base64'], + owner: sdk.programId.toBase58(), + executable: false, + rentEpoch: 0, + }, + }; +} + +export function mintAccount({ + mint, + decimals, + supply, + mintAuthority, + freezeAuthority, +}: { + mint: PublicKey; + decimals: number; + supply: BN; + mintAuthority?: PublicKey; + freezeAuthority?: PublicKey; +}) { + const data = Buffer.alloc(MintLayout.span); + + MintLayout.encode( + { + mintAuthorityOption: mintAuthority ? 1 : 0, + mintAuthority: mintAuthority || PublicKey.default, + supply: BigInt(supply.toString()), + decimals, + isInitialized: true, + freezeAuthorityOption: freezeAuthority ? 1 : 0, + freezeAuthority: freezeAuthority || PublicKey.default, + }, + data, + ); + + return { + pubkey: mint.toBase58(), + account: { + lamports: getMinimumBalanceForRentExemption(data.length), + data: [Base64.fromUint8Array(data), 'base64'], + owner: TOKEN_PROGRAM_ID.toBase58(), + executable: false, + rentEpoch: 0, + }, + }; +} + +export function metadataAccount({ + metadata, + umi, +}: { + metadata: MetadataAccountDataArgs; + umi: Umi; +}) { + return { + pubkey: findMetadataPda(umi, {mint: metadata.mint})[0], + account: { + lamports: getMinimumBalanceForRentExemption(0), + data: [ + Base64.fromUint8Array( + getMetadataAccountDataSerializer().serialize(metadata), + ), + 'base64', + ], + owner: MPL_TOKEN_METADATA_PROGRAM_ID, + executable: false, + rentEpoch: 0, + }, + }; +} diff --git a/solana/bridge_token_factory/ts/tests/src/data/index.ts b/solana/bridge_token_factory/ts/tests/src/data/index.ts new file mode 100644 index 00000000..e1eb5802 --- /dev/null +++ b/solana/bridge_token_factory/ts/tests/src/data/index.ts @@ -0,0 +1,11 @@ +import * as admin from './admin'; +import * as user from './user'; +import {programIdKp} from './common'; +import * as main from './main'; +import {OmniBridgeSolanaSDK} from 'omni-bridge-solana-sdk'; +import {Umi} from '@metaplex-foundation/umi'; +export {admin, user, programIdKp, main}; + +export function setup({sdk, umi}: {sdk: OmniBridgeSolanaSDK; umi: Umi}) { + return Promise.all([main.setup(sdk), user.setup({sdk, umi})]); +} diff --git a/solana/bridge_token_factory/ts/tests/src/data/main/index.ts b/solana/bridge_token_factory/ts/tests/src/data/main/index.ts new file mode 100644 index 00000000..58588013 --- /dev/null +++ b/solana/bridge_token_factory/ts/tests/src/data/main/index.ts @@ -0,0 +1,67 @@ +import {Keypair} from '@solana/web3.js'; +import BN from 'bn.js'; +import {ConfigAccount, OmniBridgeSolanaSDK} from 'omni-bridge-solana-sdk'; +import {getMinimumBalanceForRentExemption, omniBridgeAccount} from '../common'; +import {Base64} from 'js-base64'; +// eslint-disable-next-line n/no-unsupported-features/node-builtins +import {writeFile} from 'fs/promises'; + +export const adminKP = Keypair.fromSecretKey( + Uint8Array.from([ + 90, 63, 54, 31, 49, 125, 220, 17, 9, 70, 65, 129, 11, 206, 1, 114, 105, 83, + 26, 66, 67, 16, 75, 172, 223, 250, 181, 226, 178, 140, 223, 241, 155, 82, + 66, 23, 164, 100, 126, 190, 164, 222, 58, 234, 27, 108, 90, 122, 53, 248, + 84, 200, 33, 3, 111, 76, 67, 153, 65, 195, 182, 163, 102, 68, + ]), +); // BTJwgEmqRt4QjHtL7WwhKS9JifjqQQdLshv8EtucHdyM + +export function config(sdk: OmniBridgeSolanaSDK): ConfigAccount { + return { + admin: adminKP.publicKey, + maxUsedNonce: new BN(10), + derivedNearBridgeAddress: new Array(64).fill(0), + bumps: { + config: sdk.configId()[1], + authority: sdk.authority()[1], + solVault: sdk.solVault()[1], + wormhole: { + bridge: sdk.wormholeBridgeId()[1], + feeCollector: sdk.wormholeFeeCollectorId()[1], + sequence: sdk.wormholeSequenceId()[1], + }, + }, + }; +} + +export async function setup(sdk: OmniBridgeSolanaSDK) { + await writeFile( + '../../tests/assets/main/config.json', + JSON.stringify( + await omniBridgeAccount({ + sdk, + account: config(sdk), + accountType: 'config', + }), + undefined, + 2, + ), + ); + + await writeFile( + '../../tests/assets/main/sequence.json', + JSON.stringify( + { + pubkey: sdk.wormholeSequenceId()[0].toBase58(), + account: { + lamports: getMinimumBalanceForRentExemption(8), + data: [Base64.fromUint8Array(new BN(0).toBuffer('le', 8)), 'base64'], + owner: sdk.wormholeProgramId.toBase58(), + executable: false, + rentEpoch: 0, + }, + }, + undefined, + 2, + ), + ); +} diff --git a/solana/bridge_token_factory/ts/tests/src/data/user/index.ts b/solana/bridge_token_factory/ts/tests/src/data/user/index.ts new file mode 100644 index 00000000..a9966c3b --- /dev/null +++ b/solana/bridge_token_factory/ts/tests/src/data/user/index.ts @@ -0,0 +1,9 @@ +import {OmniBridgeSolanaSDK} from 'omni-bridge-solana-sdk'; +import * as logMetadata from './logMetadata'; +import {Umi} from '@metaplex-foundation/umi'; + +export {logMetadata}; + +export function setup({sdk, umi}: {sdk: OmniBridgeSolanaSDK; umi: Umi}) { + return Promise.all([logMetadata.setup({sdk, umi})]); +} diff --git a/solana/bridge_token_factory/ts/tests/src/data/user/logMetadata/index.ts b/solana/bridge_token_factory/ts/tests/src/data/user/logMetadata/index.ts new file mode 100644 index 00000000..28b81f3e --- /dev/null +++ b/solana/bridge_token_factory/ts/tests/src/data/user/logMetadata/index.ts @@ -0,0 +1,10 @@ +import {OmniBridgeSolanaSDK} from 'omni-bridge-solana-sdk'; +import * as noMetadata from './noMetadata'; +import * as mplMetadata from './mplMetadata'; +import {Umi} from '@metaplex-foundation/umi'; + +export {noMetadata, mplMetadata}; + +export function setup({sdk, umi}: {sdk: OmniBridgeSolanaSDK; umi: Umi}) { + return Promise.all([noMetadata.setup(sdk), mplMetadata.setup({sdk, umi})]); +} diff --git a/solana/bridge_token_factory/ts/tests/src/data/user/logMetadata/mplMetadata.ts b/solana/bridge_token_factory/ts/tests/src/data/user/logMetadata/mplMetadata.ts new file mode 100644 index 00000000..720d3c60 --- /dev/null +++ b/solana/bridge_token_factory/ts/tests/src/data/user/logMetadata/mplMetadata.ts @@ -0,0 +1,51 @@ +/* eslint-disable n/no-unsupported-features/node-builtins */ +import {PublicKey} from '@solana/web3.js'; +import BN from 'bn.js'; +import {writeFile} from 'fs/promises'; +import {metadataAccount, mintAccount} from '../../common'; +import {OmniBridgeSolanaSDK} from 'omni-bridge-solana-sdk'; +import {Program} from '@coral-xyz/anchor'; +import { + getMetadataAccountDataSerializer, + Metadata, + MetadataAccountDataArgs, +} from '@metaplex-foundation/mpl-token-metadata'; +import {publicKey} from '@metaplex-foundation/umi-public-keys'; +import {Umi} from '@metaplex-foundation/umi'; + +export const mint = { + mint: new PublicKey('2iSA1BhgQpLPvZeQTJ6quTaGWRYc6AWcVYn2L4CaMxVJ'), + decimals: 9, + supply: new BN('833232200'), + mintAuthority: new PublicKey('Ck7CqBfeFdbbg68iUCBXiZ5dEyqpQXzSnN7E2CZGtGqP'), +}; + +export const metadata: MetadataAccountDataArgs = { + updateAuthority: publicKey('Ck7CqBfeFdbbg68iUCBXiZ5dEyqpQXzSnN7E2CZGtGqP'), + mint: publicKey(mint.mint), + name: 'Name', + symbol: 'Smb', + uri: 'Uri', + sellerFeeBasisPoints: 0, + creators: [], + primarySaleHappened: false, + isMutable: false, + editionNonce: 0, + tokenStandard: null, + collection: null, + uses: null, + collectionDetails: null, + programmableConfig: null, +}; + +export async function setup({umi}: {sdk: OmniBridgeSolanaSDK; umi: Umi}) { + await writeFile( + '../../tests/assets/user/logMetadata/mplMetadata/mint.json', + JSON.stringify(mintAccount(mint), undefined, 2), + ); + + await writeFile( + '../../tests/assets/user/logMetadata/mplMetadata/metadata.json', + JSON.stringify(metadataAccount({metadata, umi}), undefined, 2), + ); +} diff --git a/solana/bridge_token_factory/ts/tests/src/data/user/logMetadata/noMetadata.ts b/solana/bridge_token_factory/ts/tests/src/data/user/logMetadata/noMetadata.ts new file mode 100644 index 00000000..f88162db --- /dev/null +++ b/solana/bridge_token_factory/ts/tests/src/data/user/logMetadata/noMetadata.ts @@ -0,0 +1,20 @@ +/* eslint-disable n/no-unsupported-features/node-builtins */ +import {PublicKey} from '@solana/web3.js'; +import BN from 'bn.js'; +import {writeFile} from 'fs/promises'; +import {mintAccount} from '../../common'; +import {OmniBridgeSolanaSDK} from 'omni-bridge-solana-sdk'; + +export const mint = { + mint: new PublicKey('7K92wLm7Gfy3tgBVmxGyA5ueyYnx5gML1SHsAonby8ay'), + decimals: 6, + supply: new BN('32769834'), + mintAuthority: new PublicKey('Fi9u6RrCyU78F7Nv7hBruQn4xbqti9jNj1xwvE2FkmY8'), +}; + +export async function setup(_sdk: OmniBridgeSolanaSDK) { + await writeFile( + '../../tests/assets/user/logMetadata/noMetadata/mint.json', + JSON.stringify(await mintAccount(mint), undefined, 2), + ); +} diff --git a/solana/bridge_token_factory/ts/tests/src/jestSetup.ts b/solana/bridge_token_factory/ts/tests/src/jestSetup.ts new file mode 100644 index 00000000..f8cd3215 --- /dev/null +++ b/solana/bridge_token_factory/ts/tests/src/jestSetup.ts @@ -0,0 +1,22 @@ +// eslint-disable-next-line n/no-unpublished-import +import {expect} from '@jest/globals'; +import {PublicKey} from '@solana/web3.js'; +import BN from 'bn.js'; + +/** + * Equality testers for jest to compare BN and PublicKey. + */ +expect.addEqualityTesters([ + (a, b) => { + if (BN.isBN(a)) { + return a.eq(b as BN); + } + return undefined; + }, + (a, b) => { + if (((a && a[Symbol.toStringTag]) || '').startsWith('PublicKey')) { + return a.equals(b as PublicKey); + } + return undefined; + }, +]); diff --git a/solana/bridge_token_factory/ts/tests/src/main.ts b/solana/bridge_token_factory/ts/tests/src/main.ts new file mode 100644 index 00000000..b7b6a51e --- /dev/null +++ b/solana/bridge_token_factory/ts/tests/src/main.ts @@ -0,0 +1,24 @@ +import {AnchorProvider, Wallet} from '@coral-xyz/anchor'; +import {Connection, Keypair, PublicKey} from '@solana/web3.js'; +import {OmniBridgeSolanaSDK} from 'omni-bridge-solana-sdk'; +import {setup} from './data'; +import {createUmi} from '@metaplex-foundation/umi-bundle-defaults'; + +const provider = new AnchorProvider( + new Connection('http://localhost:8899'), + new Wallet(Keypair.generate()), + {}, +); + +const umi = createUmi(provider.connection); + +const sdk = new OmniBridgeSolanaSDK({ + provider, + wormholeProgramId: new PublicKey( + 'worm2ZoG2kUd4vFXhvjh93UUH596ayRfgQ2MgjNMTth', + ), +}); + +setup({sdk, umi}).catch(e => { + throw e; +}); diff --git a/solana/bridge_token_factory/ts/tests/tsconfig.json b/solana/bridge_token_factory/ts/tests/tsconfig.json new file mode 100644 index 00000000..034ef270 --- /dev/null +++ b/solana/bridge_token_factory/ts/tests/tsconfig.json @@ -0,0 +1,11 @@ +{ + "compilerOptions": { + "types": ["jest"], + "typeRoots": ["./node_modules/@types"], + "lib": ["es2015"], + "module": "commonjs", + "target": "es6", + "esModuleInterop": true, + "resolveJsonModule": true + } +} From ae829baae466a287a1658d2cddff8c7a6b322fbc Mon Sep 17 00:00:00 2001 From: aankor Date: Sun, 1 Dec 2024 13:09:52 +0100 Subject: [PATCH 2/2] Add initTransfer tests --- solana/bridge_token_factory/tests/Test.toml | 6 + .../tests/assets/main/solVault.json | 13 ++ .../user/initTransfer/bridged/mint.json | 13 ++ .../user/initTransfer/bridged/owner.json | 13 ++ .../user/initTransfer/bridged/token.json | 13 ++ .../assets/user/initTransfer/native/mint.json | 13 ++ .../user/initTransfer/native/owner.json | 13 ++ .../user/initTransfer/native/token.json | 13 ++ .../user/initTransfer/native/vault.json | 13 ++ .../bridge_token_factory/ts/sdk/src/index.ts | 99 ++++++++++++ .../{admin => special}/initialize.spec.ts | 0 .../tests/__tests__/user/initTransfer.spec.ts | 148 ++++++++++++++++++ .../tests/__tests__/user/logMetadata.spec.ts | 53 +++---- .../ts/tests/package.json | 2 +- .../ts/tests/src/data/index.ts | 2 +- .../ts/tests/src/data/main/index.ts | 18 ++- .../ts/tests/src/data/user/index.ts | 8 +- .../src/data/user/initTransfer/bridged.ts | 69 ++++++++ .../tests/src/data/user/initTransfer/index.ts | 10 ++ .../src/data/user/initTransfer/native.ts | 75 +++++++++ .../src/data/user/logMetadata/mplMetadata.ts | 4 +- .../src/data/user/logMetadata/noMetadata.ts | 4 +- .../ts/tests/src/data/{common.ts => utils.ts} | 106 +++++++++++-- 23 files changed, 656 insertions(+), 52 deletions(-) create mode 100644 solana/bridge_token_factory/tests/assets/main/solVault.json create mode 100644 solana/bridge_token_factory/tests/assets/user/initTransfer/bridged/mint.json create mode 100644 solana/bridge_token_factory/tests/assets/user/initTransfer/bridged/owner.json create mode 100644 solana/bridge_token_factory/tests/assets/user/initTransfer/bridged/token.json create mode 100644 solana/bridge_token_factory/tests/assets/user/initTransfer/native/mint.json create mode 100644 solana/bridge_token_factory/tests/assets/user/initTransfer/native/owner.json create mode 100644 solana/bridge_token_factory/tests/assets/user/initTransfer/native/token.json create mode 100644 solana/bridge_token_factory/tests/assets/user/initTransfer/native/vault.json rename solana/bridge_token_factory/ts/tests/__tests__/{admin => special}/initialize.spec.ts (100%) create mode 100644 solana/bridge_token_factory/ts/tests/__tests__/user/initTransfer.spec.ts create mode 100644 solana/bridge_token_factory/ts/tests/src/data/user/initTransfer/bridged.ts create mode 100644 solana/bridge_token_factory/ts/tests/src/data/user/initTransfer/index.ts create mode 100644 solana/bridge_token_factory/ts/tests/src/data/user/initTransfer/native.ts rename solana/bridge_token_factory/ts/tests/src/data/{common.ts => utils.ts} (61%) diff --git a/solana/bridge_token_factory/tests/Test.toml b/solana/bridge_token_factory/tests/Test.toml index c18a254b..ea9ec28d 100644 --- a/solana/bridge_token_factory/tests/Test.toml +++ b/solana/bridge_token_factory/tests/Test.toml @@ -19,5 +19,11 @@ directory = "tests/assets/user/logMetadata/noMetadata" [[test.validator.account_dir]] directory = "tests/assets/user/logMetadata/mplMetadata" +[[test.validator.account_dir]] +directory = "tests/assets/user/initTransfer/native" + +[[test.validator.account_dir]] +directory = "tests/assets/user/initTransfer/bridged" + [scripts] test = "pnpm _test" \ No newline at end of file diff --git a/solana/bridge_token_factory/tests/assets/main/solVault.json b/solana/bridge_token_factory/tests/assets/main/solVault.json new file mode 100644 index 00000000..70730439 --- /dev/null +++ b/solana/bridge_token_factory/tests/assets/main/solVault.json @@ -0,0 +1,13 @@ +{ + "pubkey": "DcP7sep6ySGF76bwPVFeL3c9o5FBxaWARHPtR8bAiT3W", + "account": { + "lamports": 890880, + "data": [ + "", + "base64" + ], + "owner": "11111111111111111111111111111111", + "executable": false, + "rentEpoch": 0 + } +} \ No newline at end of file diff --git a/solana/bridge_token_factory/tests/assets/user/initTransfer/bridged/mint.json b/solana/bridge_token_factory/tests/assets/user/initTransfer/bridged/mint.json new file mode 100644 index 00000000..03724b23 --- /dev/null +++ b/solana/bridge_token_factory/tests/assets/user/initTransfer/bridged/mint.json @@ -0,0 +1,13 @@ +{ + "pubkey": "ConfcygdbvZyNQjGjsi2rePyk3JPLXoQ7E5NAWCnF4Zd", + "account": { + "lamports": 1461600, + "data": [ + "AQAAAI0hzjjxLJ6JiaJI9CZxRv2dlfYMzfr+/w66dnV3qDk78isxPhIAAAAGAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==", + "base64" + ], + "owner": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA", + "executable": false, + "rentEpoch": 0 + } +} \ No newline at end of file diff --git a/solana/bridge_token_factory/tests/assets/user/initTransfer/bridged/owner.json b/solana/bridge_token_factory/tests/assets/user/initTransfer/bridged/owner.json new file mode 100644 index 00000000..ce360b4d --- /dev/null +++ b/solana/bridge_token_factory/tests/assets/user/initTransfer/bridged/owner.json @@ -0,0 +1,13 @@ +{ + "pubkey": "3ZNCkTisRtqjvwtDqqB9Vk1KKBTW6QEPybQB4aAHbKag", + "account": { + "lamports": 6789883836, + "data": [ + "", + "base64" + ], + "owner": "11111111111111111111111111111111", + "executable": false, + "rentEpoch": 0 + } +} \ No newline at end of file diff --git a/solana/bridge_token_factory/tests/assets/user/initTransfer/bridged/token.json b/solana/bridge_token_factory/tests/assets/user/initTransfer/bridged/token.json new file mode 100644 index 00000000..1f3942f6 --- /dev/null +++ b/solana/bridge_token_factory/tests/assets/user/initTransfer/bridged/token.json @@ -0,0 +1,13 @@ +{ + "pubkey": "6i5KGd8Lb3zxYggVV3cSgfNkzQTnBnrpgTANqmiFHJLi", + "account": { + "lamports": 2039280, + "data": [ + "r2zocJc2NARMoY6O3PTc1eBx6kKmJY//viNnyiIre3AmAe7+eudS1ue6TFpQNqWtKgC3g3FpA6D6dxiQxQ5W2VWehy4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", + "base64" + ], + "owner": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA", + "executable": false, + "rentEpoch": 0 + } +} \ No newline at end of file diff --git a/solana/bridge_token_factory/tests/assets/user/initTransfer/native/mint.json b/solana/bridge_token_factory/tests/assets/user/initTransfer/native/mint.json new file mode 100644 index 00000000..6453378a --- /dev/null +++ b/solana/bridge_token_factory/tests/assets/user/initTransfer/native/mint.json @@ -0,0 +1,13 @@ +{ + "pubkey": "6evD8mRBKMmca4iFF9SS9a8sdoaSzpg2tXt8z5J6HTts", + "account": { + "lamports": 1461600, + "data": [ + "AQAAAC8uvK4lfw4BojDMkKKzhd+/gpMW5npRMUitneZcBudPb+zcBQEAAAAGAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==", + "base64" + ], + "owner": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA", + "executable": false, + "rentEpoch": 0 + } +} \ No newline at end of file diff --git a/solana/bridge_token_factory/tests/assets/user/initTransfer/native/owner.json b/solana/bridge_token_factory/tests/assets/user/initTransfer/native/owner.json new file mode 100644 index 00000000..88341943 --- /dev/null +++ b/solana/bridge_token_factory/tests/assets/user/initTransfer/native/owner.json @@ -0,0 +1,13 @@ +{ + "pubkey": "EfB7cLDAC7xq29hfEEJARmzYDPBHnijL9JCc1xMkXSur", + "account": { + "lamports": 79083248088, + "data": [ + "", + "base64" + ], + "owner": "11111111111111111111111111111111", + "executable": false, + "rentEpoch": 0 + } +} \ No newline at end of file diff --git a/solana/bridge_token_factory/tests/assets/user/initTransfer/native/token.json b/solana/bridge_token_factory/tests/assets/user/initTransfer/native/token.json new file mode 100644 index 00000000..27c981e7 --- /dev/null +++ b/solana/bridge_token_factory/tests/assets/user/initTransfer/native/token.json @@ -0,0 +1,13 @@ +{ + "pubkey": "Doeb6p1hiUMfg9331QP5U8UvkWQN8w2ZvXRjMcfukB2q", + "account": { + "lamports": 2039280, + "data": [ + "VAEWod+7dswcImUUbIUYppMOdhT8xcaaXR/nK/iYGVjK72/Jfl2sGdns0MGRr1qAuIe5Kv8hh7ywn3tUUt20HYRHjQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", + "base64" + ], + "owner": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA", + "executable": false, + "rentEpoch": 0 + } +} \ No newline at end of file diff --git a/solana/bridge_token_factory/tests/assets/user/initTransfer/native/vault.json b/solana/bridge_token_factory/tests/assets/user/initTransfer/native/vault.json new file mode 100644 index 00000000..22222f53 --- /dev/null +++ b/solana/bridge_token_factory/tests/assets/user/initTransfer/native/vault.json @@ -0,0 +1,13 @@ +{ + "pubkey": "CCUpAhM1emxgJ8i9ESuD4NPpD16z4Hw3wcCXGBhHRv3Q", + "account": { + "lamports": 2039280, + "data": [ + "VAEWod+7dswcImUUbIUYppMOdhT8xcaaXR/nK/iYGViNIc448SyeiYmiSPQmcUb9nZX2DM36/v8OunZ1d6g5O4AdAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", + "base64" + ], + "owner": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA", + "executable": false, + "rentEpoch": 0 + } +} \ No newline at end of file diff --git a/solana/bridge_token_factory/ts/sdk/src/index.ts b/solana/bridge_token_factory/ts/sdk/src/index.ts index 8d90353f..f76f94f2 100644 --- a/solana/bridge_token_factory/ts/sdk/src/index.ts +++ b/solana/bridge_token_factory/ts/sdk/src/index.ts @@ -687,4 +687,103 @@ export class OmniBridgeSolanaSDK { message: wormholeMessage.publicKey, }; } + + static parseWormholeMessage(message: Buffer) { + let offset = 0; + const messageType = message.readInt8(offset); + offset += 1; + switch (messageType) { + case 0: { + let chainId = message.readInt8(offset); + offset += 1; + if (chainId !== 2) { + throw new Error(`Sender has not solana chain ID: ${chainId}`); + } + + const sender = new PublicKey(message.subarray(offset, offset + 32)); + offset += 32; + + chainId = message.readInt8(offset); + offset += 1; + if (chainId !== 2) { + throw new Error(`Mint has not solana chain ID: ${chainId}`); + } + + const mint = new PublicKey(message.subarray(offset, offset + 32)); + offset += 32; + + const nonce = new BN(message.subarray(offset, offset + 8), 'le'); + offset += 8; + + const amount = new BN(message.subarray(offset, offset + 16), 'le'); + offset += 16; + + const fee = new BN(message.subarray(offset, offset + 16), 'le'); + offset += 16; + + const nativeFee = new BN(message.subarray(offset, offset + 16), 'le'); + offset += 16; + + const recipientLength = message.readInt32LE(offset); + offset += 4; + const recipient = message.toString( + 'utf-8', + offset, + offset + recipientLength, + ); + offset += recipientLength; + + const messageLength = message.readUInt32LE(offset); + offset += 4; + const messageData = message.subarray(offset, offset + messageLength); + + return { + messageType: 'initTransfer', + sender, + mint, + nonce, + amount, + fee, + nativeFee, + recipient, + messageData, + }; + } + case 3: { + // LogMetadata + + const chainId = message.readInt8(offset); + offset += 1; + if (chainId !== 2) { + throw new Error(`Mint has not solana chain ID: ${chainId}`); + } + + const mint = new PublicKey(message.subarray(offset, offset + 32)); + offset += 32; + + const nameLength = message.readUInt32LE(offset); + offset += 4; + const name = message.toString('utf-8', offset, offset + nameLength); + offset += nameLength; + + const symbolLength = message.readUInt32LE(offset); + offset += 4; + const symbol = message.toString('utf-8', offset, offset + symbolLength); + offset += symbolLength; + + const decimals = message.readInt8(offset); + offset += 1; + + return { + messageType: 'logMetadata', + mint, + name, + symbol, + decimals, + }; + } + default: + throw new Error(`Unknown message type: ${messageType}`); + } + } } diff --git a/solana/bridge_token_factory/ts/tests/__tests__/admin/initialize.spec.ts b/solana/bridge_token_factory/ts/tests/__tests__/special/initialize.spec.ts similarity index 100% rename from solana/bridge_token_factory/ts/tests/__tests__/admin/initialize.spec.ts rename to solana/bridge_token_factory/ts/tests/__tests__/special/initialize.spec.ts diff --git a/solana/bridge_token_factory/ts/tests/__tests__/user/initTransfer.spec.ts b/solana/bridge_token_factory/ts/tests/__tests__/user/initTransfer.spec.ts new file mode 100644 index 00000000..4528e1d7 --- /dev/null +++ b/solana/bridge_token_factory/ts/tests/__tests__/user/initTransfer.spec.ts @@ -0,0 +1,148 @@ +import {AnchorProvider} from '@coral-xyz/anchor'; +import {PublicKey, Transaction} from '@solana/web3.js'; +import {OmniBridgeSolanaSDK} from 'omni-bridge-solana-sdk'; +import * as data from '../../src/data/user/initTransfer'; +import {BN} from 'bn.js'; +import {getAssociatedTokenAddressSync} from '@solana/spl-token'; + +describe('logMetadata', () => { + let sdk: OmniBridgeSolanaSDK; + + beforeAll(() => { + sdk = new OmniBridgeSolanaSDK({ + provider: AnchorProvider.local(), + wormholeProgramId: new PublicKey( + 'worm2ZoG2kUd4vFXhvjh93UUH596ayRfgQ2MgjNMTth', + ), + }); + }); + + it('Inits native transfer', async () => { + const { + mint, + amount, + recipient, + fee, + nativeFee, + owner, + ownerBalance, + tokenBalance, + vaultBalance, + } = data.native; + + const tx = new Transaction(); + const {instructions, signers, message} = await sdk.initTransfer({ + mint: mint.mint, + amount, + user: owner.publicKey, + recipient, + fee, + nativeFee, + }); + tx.add(...instructions); + + await expect( + sdk.provider.sendAndConfirm!(tx, [...signers, owner]), + ).resolves.toBeTruthy(); + + await expect( + sdk.provider.connection + .getAccountInfo(message) + .then(({data}) => + OmniBridgeSolanaSDK.parseWormholeMessage(data.subarray(95)), + ), + ).resolves.toStrictEqual({ + messageType: 'initTransfer', + sender: owner.publicKey, + mint: mint.mint, + nonce: expect.any(BN), + amount, + fee, + nativeFee, + recipient, + messageData: Buffer.alloc(0), + }); + + await expect( + sdk.provider.connection + .getTokenAccountBalance( + getAssociatedTokenAddressSync(mint.mint, owner.publicKey), + ) + .then(({value}) => value.amount), + ).resolves.toStrictEqual(tokenBalance.sub(amount).toString()); + await expect( + sdk.provider.connection + .getTokenAccountBalance(sdk.vaultId({mint: mint.mint})[0]) + .then(({value}) => value.amount), + ).resolves.toStrictEqual(vaultBalance.add(amount).toString()); + + await expect( + sdk.provider.connection.getBalance(owner.publicKey), + ).resolves.toStrictEqual(ownerBalance.sub(nativeFee).toNumber()); + }); + + it('Inits bridged transfer', async () => { + const { + nearToken, + mint, + amount, + recipient, + fee, + nativeFee, + owner, + ownerBalance, + tokenBalance, + } = data.bridged; + const [mintId] = sdk.wrappedMintId({token: nearToken}); + + const tx = new Transaction(); + const {instructions, signers, message} = await sdk.initTransfer({ + token: nearToken, + amount, + user: owner.publicKey, + recipient, + fee, + nativeFee, + }); + tx.add(...instructions); + + await expect( + sdk.provider.sendAndConfirm!(tx, [...signers, owner]), + ).resolves.toBeTruthy(); + + await expect( + sdk.provider.connection + .getAccountInfo(message) + .then(({data}) => + OmniBridgeSolanaSDK.parseWormholeMessage(data.subarray(95)), + ), + ).resolves.toStrictEqual({ + messageType: 'initTransfer', + sender: owner.publicKey, + mint: mintId, + nonce: expect.any(BN), + amount, + fee, + nativeFee, + recipient, + messageData: Buffer.alloc(0), + }); + + await expect( + sdk.provider.connection + .getTokenAccountBalance( + getAssociatedTokenAddressSync(mintId, owner.publicKey), + ) + .then(({value}) => value.amount), + ).resolves.toStrictEqual(tokenBalance.sub(amount).toString()); + await expect( + sdk.provider.connection + .getTokenSupply(mintId) + .then(({value}) => value.amount), + ).resolves.toStrictEqual(mint.supply.sub(amount).toString()); + + await expect( + sdk.provider.connection.getBalance(owner.publicKey), + ).resolves.toStrictEqual(ownerBalance.sub(nativeFee).toNumber()); + }); +}); diff --git a/solana/bridge_token_factory/ts/tests/__tests__/user/logMetadata.spec.ts b/solana/bridge_token_factory/ts/tests/__tests__/user/logMetadata.spec.ts index ef76275a..1f856307 100644 --- a/solana/bridge_token_factory/ts/tests/__tests__/user/logMetadata.spec.ts +++ b/solana/bridge_token_factory/ts/tests/__tests__/user/logMetadata.spec.ts @@ -26,20 +26,20 @@ describe('logMetadata', () => { await expect( sdk.provider.sendAndConfirm!(tx, [...signers]), ).resolves.toBeTruthy(); - const messageData = Buffer.alloc(43); - messageData.writeInt8(3, 0); // LogMetadata - messageData.writeInt8(2, 1); // SOLANA_OMNI_BRIDGE_CHAIN_ID - mint.mint.toBuffer().copy(messageData, 2); // mint - // Name - messageData.writeUint32LE(0, 34); - // Symbol - messageData.writeUint32LE(0, 38); - messageData.writeInt8(mint.decimals, 42); // Decimals + await expect( sdk.provider.connection .getAccountInfo(message) - .then(({data}) => data.subarray(95)), - ).resolves.toStrictEqual(messageData); + .then(({data}) => + OmniBridgeSolanaSDK.parseWormholeMessage(data.subarray(95)), + ), + ).resolves.toStrictEqual({ + messageType: 'logMetadata', + mint: mint.mint, + name: '', + symbol: '', + decimals: mint.decimals, + }); await expect( sdk.provider.connection @@ -71,29 +71,20 @@ describe('logMetadata', () => { await expect( sdk.provider.sendAndConfirm!(tx, [...signers]), ).resolves.toBeTruthy(); - const messageData = Buffer.alloc( - 43 + metadata.name.length + metadata.symbol.length, - ); - messageData.writeInt8(3, 0); // LogMetadata - messageData.writeInt8(2, 1); // SOLANA_OMNI_BRIDGE_CHAIN_ID - mint.mint.toBuffer().copy(messageData, 2); // mint - let offset = 34; - // Name - messageData.writeUint32LE(metadata.name.length, offset); - offset += 4; - messageData.write(metadata.name, offset); - offset += metadata.name.length; - // Symbol - messageData.writeUint32LE(metadata.symbol.length, offset); - offset += 4; - messageData.write(metadata.symbol, offset); - offset += metadata.symbol.length; - messageData.writeInt8(mint.decimals, offset); // Decimals + await expect( sdk.provider.connection .getAccountInfo(message) - .then(({data}) => data.subarray(95)), - ).resolves.toStrictEqual(messageData); + .then(({data}) => + OmniBridgeSolanaSDK.parseWormholeMessage(data.subarray(95)), + ), + ).resolves.toStrictEqual({ + messageType: 'logMetadata', + mint: mint.mint, + name: metadata.name, + symbol: metadata.symbol, + decimals: mint.decimals, + }); await expect( sdk.provider.connection diff --git a/solana/bridge_token_factory/ts/tests/package.json b/solana/bridge_token_factory/ts/tests/package.json index 100b27fa..ba13bcf8 100644 --- a/solana/bridge_token_factory/ts/tests/package.json +++ b/solana/bridge_token_factory/ts/tests/package.json @@ -5,7 +5,7 @@ "main": "index.js", "scripts": { "test-initialize-simple": "jest -t 'Initializes in the simple case'", - "test": "jest -t logMetadata", + "test": "jest --testPathPattern=user", "lint": "gts lint", "clean": "gts clean", "compile": "tsc", diff --git a/solana/bridge_token_factory/ts/tests/src/data/index.ts b/solana/bridge_token_factory/ts/tests/src/data/index.ts index e1eb5802..ae1ca407 100644 --- a/solana/bridge_token_factory/ts/tests/src/data/index.ts +++ b/solana/bridge_token_factory/ts/tests/src/data/index.ts @@ -1,6 +1,6 @@ import * as admin from './admin'; import * as user from './user'; -import {programIdKp} from './common'; +import {programIdKp} from './utils'; import * as main from './main'; import {OmniBridgeSolanaSDK} from 'omni-bridge-solana-sdk'; import {Umi} from '@metaplex-foundation/umi'; diff --git a/solana/bridge_token_factory/ts/tests/src/data/main/index.ts b/solana/bridge_token_factory/ts/tests/src/data/main/index.ts index 58588013..7aa4af81 100644 --- a/solana/bridge_token_factory/ts/tests/src/data/main/index.ts +++ b/solana/bridge_token_factory/ts/tests/src/data/main/index.ts @@ -1,7 +1,11 @@ import {Keypair} from '@solana/web3.js'; import BN from 'bn.js'; import {ConfigAccount, OmniBridgeSolanaSDK} from 'omni-bridge-solana-sdk'; -import {getMinimumBalanceForRentExemption, omniBridgeAccount} from '../common'; +import { + getMinimumBalanceForRentExemption, + omniBridgeAccount, + systemAccount, +} from '../utils'; import {Base64} from 'js-base64'; // eslint-disable-next-line n/no-unsupported-features/node-builtins import {writeFile} from 'fs/promises'; @@ -47,6 +51,18 @@ export async function setup(sdk: OmniBridgeSolanaSDK) { ), ); + await writeFile( + '../../tests/assets/main/solVault.json', + JSON.stringify( + systemAccount({ + balance: new BN(getMinimumBalanceForRentExemption(0)), + address: sdk.solVault()[0], + }), + undefined, + 2, + ), + ); + await writeFile( '../../tests/assets/main/sequence.json', JSON.stringify( diff --git a/solana/bridge_token_factory/ts/tests/src/data/user/index.ts b/solana/bridge_token_factory/ts/tests/src/data/user/index.ts index a9966c3b..1e3e8485 100644 --- a/solana/bridge_token_factory/ts/tests/src/data/user/index.ts +++ b/solana/bridge_token_factory/ts/tests/src/data/user/index.ts @@ -1,9 +1,13 @@ import {OmniBridgeSolanaSDK} from 'omni-bridge-solana-sdk'; import * as logMetadata from './logMetadata'; +import * as initTransfer from './initTransfer'; import {Umi} from '@metaplex-foundation/umi'; -export {logMetadata}; +export {logMetadata, initTransfer}; export function setup({sdk, umi}: {sdk: OmniBridgeSolanaSDK; umi: Umi}) { - return Promise.all([logMetadata.setup({sdk, umi})]); + return Promise.all([ + logMetadata.setup({sdk, umi}), + initTransfer.setup({sdk, umi}), + ]); } diff --git a/solana/bridge_token_factory/ts/tests/src/data/user/initTransfer/bridged.ts b/solana/bridge_token_factory/ts/tests/src/data/user/initTransfer/bridged.ts new file mode 100644 index 00000000..d70beeb9 --- /dev/null +++ b/solana/bridge_token_factory/ts/tests/src/data/user/initTransfer/bridged.ts @@ -0,0 +1,69 @@ +/* eslint-disable n/no-unsupported-features/node-builtins */ +import {Keypair, PublicKey} from '@solana/web3.js'; +import BN from 'bn.js'; +import {writeFile} from 'fs/promises'; +import { + mintAccount, + MintAccountArgs, + systemAccount, + tokenAccount, + TokenAccountArgs, +} from '../../utils'; +import {OmniBridgeSolanaSDK} from 'omni-bridge-solana-sdk'; + +export const nearToken = 'The token'; + +export const mint: Omit, 'mintAuthority'> = { + decimals: 6, + supply: new BN('78352821234'), +}; + +export const owner = Keypair.fromSecretKey( + new Uint8Array([ + 200, 192, 104, 178, 210, 27, 92, 22, 180, 120, 58, 14, 205, 78, 60, 148, 4, + 219, 162, 33, 205, 127, 39, 246, 185, 231, 102, 182, 115, 241, 76, 131, 38, + 1, 238, 254, 122, 231, 82, 214, 231, 186, 76, 90, 80, 54, 165, 173, 42, 0, + 183, 131, 113, 105, 3, 160, 250, 119, 24, 144, 197, 14, 86, 217, + ]), +); // 3ZNCkTisRtqjvwtDqqB9Vk1KKBTW6QEPybQB4aAHbKag + +export const ownerBalance = new BN('6789883836'); + +export const tokenBalance = new BN('780639829'); + +export const amount = new BN('825784'); + +export const recipient = 'The Recepient'; +export const fee = new BN(344); +export const nativeFee = new BN(22); + +export async function setup({sdk}: {sdk: OmniBridgeSolanaSDK}) { + const [mintId] = sdk.wrappedMintId({token: nearToken}); + const token: TokenAccountArgs = { + mint: mintId, + owner: owner.publicKey, + amount: tokenBalance, + }; + + await writeFile( + '../../tests/assets/user/initTransfer/bridged/mint.json', + JSON.stringify( + mintAccount({mint: mintId, mintAuthority: sdk.authority()[0], ...mint}), + undefined, + 2, + ), + ); + + await writeFile( + '../../tests/assets/user/initTransfer/bridged/owner.json', + JSON.stringify( + systemAccount({address: owner.publicKey, balance: ownerBalance}), + undefined, + 2, + ), + ); + await writeFile( + '../../tests/assets/user/initTransfer/bridged/token.json', + JSON.stringify(tokenAccount(token), undefined, 2), + ); +} diff --git a/solana/bridge_token_factory/ts/tests/src/data/user/initTransfer/index.ts b/solana/bridge_token_factory/ts/tests/src/data/user/initTransfer/index.ts new file mode 100644 index 00000000..3caddb8e --- /dev/null +++ b/solana/bridge_token_factory/ts/tests/src/data/user/initTransfer/index.ts @@ -0,0 +1,10 @@ +import {OmniBridgeSolanaSDK} from 'omni-bridge-solana-sdk'; +import * as native from './native'; +import * as bridged from './bridged'; +import {Umi} from '@metaplex-foundation/umi'; + +export {native, bridged}; + +export function setup({sdk, umi}: {sdk: OmniBridgeSolanaSDK; umi: Umi}) { + return Promise.all([native.setup({sdk}), bridged.setup({sdk})]); +} diff --git a/solana/bridge_token_factory/ts/tests/src/data/user/initTransfer/native.ts b/solana/bridge_token_factory/ts/tests/src/data/user/initTransfer/native.ts new file mode 100644 index 00000000..c238f335 --- /dev/null +++ b/solana/bridge_token_factory/ts/tests/src/data/user/initTransfer/native.ts @@ -0,0 +1,75 @@ +/* eslint-disable n/no-unsupported-features/node-builtins */ +import {Keypair, PublicKey} from '@solana/web3.js'; +import BN from 'bn.js'; +import {writeFile} from 'fs/promises'; +import { + mintAccount, + MintAccountArgs, + systemAccount, + tokenAccount, + TokenAccountArgs, +} from '../../utils'; +import {OmniBridgeSolanaSDK} from 'omni-bridge-solana-sdk'; + +export const mint: MintAccountArgs = { + mint: new PublicKey('6evD8mRBKMmca4iFF9SS9a8sdoaSzpg2tXt8z5J6HTts'), + decimals: 6, + supply: new BN('4393331823'), + mintAuthority: new PublicKey('4BBVnRsidYiAQhg4j3xuWgUS9VDuVYNXgPEQ2p3o2NuC'), +}; + +export const owner = Keypair.fromSecretKey( + new Uint8Array([ + 1, 80, 208, 118, 238, 134, 103, 184, 50, 27, 38, 59, 43, 244, 148, 191, 199, + 229, 212, 188, 156, 239, 82, 3, 55, 53, 178, 67, 167, 74, 150, 75, 202, 239, + 111, 201, 126, 93, 172, 25, 217, 236, 208, 193, 145, 175, 90, 128, 184, 135, + 185, 42, 255, 33, 135, 188, 176, 159, 123, 84, 82, 221, 180, 29, + ]), +); // EfB7cLDAC7xq29hfEEJARmzYDPBHnijL9JCc1xMkXSur + +export const ownerBalance = new BN('79083248088'); + +export const tokenBalance = new BN('9258884'); +export const vaultBalance = new BN('7552'); + +export const amount = new BN('92690'); + +export const recipient = 'The target'; +export const fee = new BN(2); +export const nativeFee = new BN(4); + +export async function setup({sdk}: {sdk: OmniBridgeSolanaSDK}) { + const token: TokenAccountArgs = { + mint: mint.mint, + owner: owner.publicKey, + amount: tokenBalance, + }; + + const vault: TokenAccountArgs = { + address: sdk.vaultId({mint: mint.mint})[0], + mint: mint.mint, + owner: sdk.authority()[0], + amount: vaultBalance, + }; + + await writeFile( + '../../tests/assets/user/initTransfer/native/mint.json', + JSON.stringify(mintAccount(mint), undefined, 2), + ); + await writeFile( + '../../tests/assets/user/initTransfer/native/vault.json', + JSON.stringify(tokenAccount(vault), undefined, 2), + ); + await writeFile( + '../../tests/assets/user/initTransfer/native/owner.json', + JSON.stringify( + systemAccount({address: owner.publicKey, balance: ownerBalance}), + undefined, + 2, + ), + ); + await writeFile( + '../../tests/assets/user/initTransfer/native/token.json', + JSON.stringify(tokenAccount(token), undefined, 2), + ); +} diff --git a/solana/bridge_token_factory/ts/tests/src/data/user/logMetadata/mplMetadata.ts b/solana/bridge_token_factory/ts/tests/src/data/user/logMetadata/mplMetadata.ts index 720d3c60..fe134835 100644 --- a/solana/bridge_token_factory/ts/tests/src/data/user/logMetadata/mplMetadata.ts +++ b/solana/bridge_token_factory/ts/tests/src/data/user/logMetadata/mplMetadata.ts @@ -2,7 +2,7 @@ import {PublicKey} from '@solana/web3.js'; import BN from 'bn.js'; import {writeFile} from 'fs/promises'; -import {metadataAccount, mintAccount} from '../../common'; +import {metadataAccount, mintAccount} from '../../utils'; import {OmniBridgeSolanaSDK} from 'omni-bridge-solana-sdk'; import {Program} from '@coral-xyz/anchor'; import { @@ -46,6 +46,6 @@ export async function setup({umi}: {sdk: OmniBridgeSolanaSDK; umi: Umi}) { await writeFile( '../../tests/assets/user/logMetadata/mplMetadata/metadata.json', - JSON.stringify(metadataAccount({metadata, umi}), undefined, 2), + JSON.stringify(metadataAccount({...metadata, umi}), undefined, 2), ); } diff --git a/solana/bridge_token_factory/ts/tests/src/data/user/logMetadata/noMetadata.ts b/solana/bridge_token_factory/ts/tests/src/data/user/logMetadata/noMetadata.ts index f88162db..75f8454e 100644 --- a/solana/bridge_token_factory/ts/tests/src/data/user/logMetadata/noMetadata.ts +++ b/solana/bridge_token_factory/ts/tests/src/data/user/logMetadata/noMetadata.ts @@ -2,7 +2,7 @@ import {PublicKey} from '@solana/web3.js'; import BN from 'bn.js'; import {writeFile} from 'fs/promises'; -import {mintAccount} from '../../common'; +import {mintAccount} from '../../utils'; import {OmniBridgeSolanaSDK} from 'omni-bridge-solana-sdk'; export const mint = { @@ -15,6 +15,6 @@ export const mint = { export async function setup(_sdk: OmniBridgeSolanaSDK) { await writeFile( '../../tests/assets/user/logMetadata/noMetadata/mint.json', - JSON.stringify(await mintAccount(mint), undefined, 2), + JSON.stringify(mintAccount(mint), undefined, 2), ); } diff --git a/solana/bridge_token_factory/ts/tests/src/data/common.ts b/solana/bridge_token_factory/ts/tests/src/data/utils.ts similarity index 61% rename from solana/bridge_token_factory/ts/tests/src/data/common.ts rename to solana/bridge_token_factory/ts/tests/src/data/utils.ts index 40ea3169..8fd831ff 100644 --- a/solana/bridge_token_factory/ts/tests/src/data/common.ts +++ b/solana/bridge_token_factory/ts/tests/src/data/utils.ts @@ -1,9 +1,15 @@ /* eslint-disable n/no-unsupported-features/es-builtins */ -import {Keypair, PublicKey} from '@solana/web3.js'; +import {Keypair, PublicKey, SystemProgram} from '@solana/web3.js'; import BN from 'bn.js'; import {OmniBridgeSolanaSDK} from 'omni-bridge-solana-sdk'; import {Base64} from 'js-base64'; -import {MintLayout, TOKEN_PROGRAM_ID} from '@solana/spl-token'; +import { + AccountLayout, + AccountState, + getAssociatedTokenAddressSync, + MintLayout, + TOKEN_PROGRAM_ID, +} from '@solana/spl-token'; import { findMetadataPda, getMetadataAccountDataSerializer, @@ -39,6 +45,25 @@ export const programIdKp = Keypair.fromSecretKey( ]), ); // 3ZtEZ8xABFbUr4c1FVpXbQiVdqv4vwhvfCc8HMmhEeua +export function systemAccount({ + address, + balance, +}: { + address: PublicKey; + balance: BN; +}) { + return { + pubkey: address.toBase58(), + account: { + lamports: balance.toNumber(), + data: ['', 'base64'], + owner: SystemProgram.programId.toBase58(), + executable: false, + rentEpoch: 0, + }, + }; +} + export async function omniBridgeAccount({ sdk, account, @@ -61,19 +86,21 @@ export async function omniBridgeAccount({ }; } +export type MintAccountArgs = { + mint: PublicKey; + decimals: number; + supply: BN; + mintAuthority?: PublicKey; + freezeAuthority?: PublicKey; +}; + export function mintAccount({ mint, decimals, supply, mintAuthority, freezeAuthority, -}: { - mint: PublicKey; - decimals: number; - supply: BN; - mintAuthority?: PublicKey; - freezeAuthority?: PublicKey; -}) { +}: MintAccountArgs) { const data = Buffer.alloc(MintLayout.span); MintLayout.encode( @@ -102,10 +129,9 @@ export function mintAccount({ } export function metadataAccount({ - metadata, umi, -}: { - metadata: MetadataAccountDataArgs; + ...metadata +}: MetadataAccountDataArgs & { umi: Umi; }) { return { @@ -124,3 +150,59 @@ export function metadataAccount({ }, }; } + +export type TokenAccountArgs = { + address?: PublicKey; + mint: PublicKey; + owner: PublicKey; + amount: BN; + delegate?: PublicKey | null; + isFrozen?: boolean; + native?: BN; + delegatedAmount?: BN; + closeAuthority?: PublicKey | null; +}; + +export function tokenAccount({ + address, + mint, + owner, + amount, + delegate, + isFrozen = false, + native, + delegatedAmount = new BN(0), + closeAuthority, +}: TokenAccountArgs) { + if (!address) { + address = getAssociatedTokenAddressSync(mint, owner, true); + } + const data = Buffer.alloc(AccountLayout.span); + AccountLayout.encode( + { + mint, + owner, + amount: BigInt(amount.toString()), + delegateOption: delegate ? 1 : 0, + delegate: delegate || PublicKey.default, + state: isFrozen ? AccountState.Frozen : AccountState.Initialized, + isNativeOption: native ? 1 : 0, + isNative: BigInt(native?.toString() || 0), + delegatedAmount: BigInt(delegatedAmount.toString()), + closeAuthorityOption: closeAuthority ? 1 : 0, + closeAuthority: closeAuthority || PublicKey.default, + }, + data, + ); + + return { + pubkey: address.toBase58(), + account: { + lamports: getMinimumBalanceForRentExemption(data.length), + data: [Base64.fromUint8Array(data), 'base64'], + owner: TOKEN_PROGRAM_ID.toBase58(), + executable: false, + rentEpoch: 0, + }, + }; +}