From 5da721536556326141a0c74ac40702ee3bbff640 Mon Sep 17 00:00:00 2001 From: Otniel Nicola Date: Tue, 27 Jan 2026 11:37:16 +0200 Subject: [PATCH 1/8] chore: Rename operations in README files --- src/neo/message-bridge/README.md | 18 +++++++++--------- src/neo/wallet/README.md | 2 +- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/neo/message-bridge/README.md b/src/neo/message-bridge/README.md index 3eeb689..455eab0 100644 --- a/src/neo/message-bridge/README.md +++ b/src/neo/message-bridge/README.md @@ -14,17 +14,17 @@ This directory contains examples for interacting with the Message Bridge contrac ## Available Scripts ### Message Bridge Operations -- `npm run mb:execute` - Execute a message using MESSAGE_NONCE -- `npm run mb:readonly` - Read all message bridge state information -- `npm run mb:pause` - Test all pause/unpause operations -- `npm run mb:send` - Send messages based on MESSAGE_BRIDGE_OPERATION -- `npm run mb:serialize` - Test serialization and validation methods -- `npm run mb:set-execution-manager` - Set execution manager address +- `npm run amb:execute` - Execute a message using MESSAGE_NONCE +- `npm run amb:readonly` - Read all message bridge state information +- `npm run amb:pause` - Test all pause/unpause operations +- `npm run amb:send` - Send messages based on MESSAGE_BRIDGE_OPERATION +- `npm run amb:serialize` - Test serialization and validation methods +- `npm run amb:set-execution-manager` - Set execution manager address ### Specific Message Operations -- `npm run mb:send-executable` - Send an executable message -- `npm run mb:send-result` - Send a result message -- `npm run mb:send-store-only` - Send a store-only message +- `npm run amb:send-executable` - Send an executable message +- `npm run amb:send-result` - Send a result message +- `npm run amb:send-store-only` - Send a store-only message ## Required Environment Variables diff --git a/src/neo/wallet/README.md b/src/neo/wallet/README.md index 3b5eff8..822f9d7 100644 --- a/src/neo/wallet/README.md +++ b/src/neo/wallet/README.md @@ -9,7 +9,7 @@ This directory contains examples for interacting with Neo wallets, including loa ## Available Scripts ### Wallet Operations -- `npm run wallet:operations` - Run wallet operations (load, decrypt, display balances, etc.) +- `npm run wallet` - Run wallet operations (load, decrypt, display balances, etc.) ## Required Environment Variables From 884349f825810ba88ae06fa61f316020ec36268f Mon Sep 17 00:00:00 2001 From: Otniel Nicola Date: Fri, 30 Jan 2026 11:08:39 +0200 Subject: [PATCH 2/8] feat: Add EVM examples --- package-lock.json | 255 +++++++++++++++++- package.json | 110 ++++---- src/evm/README.md | 78 ++++++ src/evm/bridge-management/README.md | 31 +++ src/evm/bridge-management/readOnlyMethods.ts | 57 ++++ src/evm/execution-manager/README.md | 26 ++ src/evm/execution-manager/executeMessage.ts | 55 ++++ src/evm/execution-manager/readOnlyMethods.ts | 43 +++ src/evm/message-bridge/README.md | 34 +++ src/evm/message-bridge/executeMessage.ts | 55 ++++ src/evm/message-bridge/pauseOperations.ts | 81 ++++++ src/evm/message-bridge/readOnlyMethods.ts | 70 +++++ src/evm/message-bridge/sendMessage.ts | 100 +++++++ src/evm/message-bridge/setExecutionManager.ts | 50 ++++ src/evm/native-bridge/README.md | 49 ++++ src/evm/native-bridge/readOnlyMethods.ts | 83 ++++++ src/evm/token-bridge/README.md | 58 ++++ src/evm/token-bridge/readOnlyMethods.ts | 134 +++++++++ src/evm/utils.ts | 100 +++++++ 19 files changed, 1414 insertions(+), 55 deletions(-) create mode 100644 src/evm/README.md create mode 100644 src/evm/bridge-management/README.md create mode 100644 src/evm/bridge-management/readOnlyMethods.ts create mode 100644 src/evm/execution-manager/README.md create mode 100644 src/evm/execution-manager/executeMessage.ts create mode 100644 src/evm/execution-manager/readOnlyMethods.ts create mode 100644 src/evm/message-bridge/README.md create mode 100644 src/evm/message-bridge/executeMessage.ts create mode 100644 src/evm/message-bridge/pauseOperations.ts create mode 100644 src/evm/message-bridge/readOnlyMethods.ts create mode 100644 src/evm/message-bridge/sendMessage.ts create mode 100644 src/evm/message-bridge/setExecutionManager.ts create mode 100644 src/evm/native-bridge/README.md create mode 100644 src/evm/native-bridge/readOnlyMethods.ts create mode 100644 src/evm/token-bridge/README.md create mode 100644 src/evm/token-bridge/readOnlyMethods.ts create mode 100644 src/evm/utils.ts diff --git a/package-lock.json b/package-lock.json index 2af069c..eff4e92 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,8 +9,9 @@ "version": "1.0.0", "license": "Apache-2.0", "dependencies": { - "@bane-labs/bridge-sdk-ts": "^1.0.0-beta.6", - "dotenv": "^17.2.3" + "@bane-labs/bridge-sdk-ts": "file:../../../bridge-sdk-ts/bane-labs-bridge-sdk-ts-1.0.0-beta.7.tgz", + "dotenv": "^17.2.3", + "viem": "^2.21.53" }, "devDependencies": { "@types/node": "^24.10.1", @@ -19,13 +20,19 @@ "typescript": "^5.9.3" } }, + "node_modules/@adraffy/ens-normalize": { + "version": "1.11.1", + "license": "MIT" + }, "node_modules/@bane-labs/bridge-sdk-ts": { - "version": "1.0.0-beta.6", - "resolved": "https://registry.npmjs.org/@bane-labs/bridge-sdk-ts/-/bridge-sdk-ts-1.0.0-beta.6.tgz", - "integrity": "sha512-35G8tit1o0BF64zZ1gu0bIE8YEf2y957IxQpkA6LQNwcCftKeAUGdGYxiLaQhZO8NiF2RNEy/fYcsyOBiYEvJg==", + "version": "1.0.0-beta.7", + "resolved": "file:../../../bridge-sdk-ts/bane-labs-bridge-sdk-ts-1.0.0-beta.7.tgz", + "integrity": "sha512-NCgKSqYcQ3FseqJ0PL9wuzjR5YEkPkyjya0nmSsiu/+dAAavM22dVH1/vToqllRO8SMKqe2aAZgB6NsL6PFzvQ==", "license": "Apache-2.0", "dependencies": { - "@cityofzion/neon-js": "5.8.0" + "@cityofzion/neon-js": "5.8.0", + "@gitmyabi/bane-labs--bridge-evm-contracts": "^0.0.5", + "viem": "^2.45.0" } }, "node_modules/@cityofzion/neon-api": { @@ -513,6 +520,13 @@ "node": ">=18" } }, + "node_modules/@gitmyabi/bane-labs--bridge-evm-contracts": { + "version": "0.0.5", + "license": "MIT", + "dependencies": { + "viem": "^2.0.0" + } + }, "node_modules/@jridgewell/resolve-uri": { "version": "3.1.2", "dev": true, @@ -626,6 +640,25 @@ "undici-types": "~7.16.0" } }, + "node_modules/abitype": { + "version": "1.2.3", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/wevm" + }, + "peerDependencies": { + "typescript": ">=5.0.4", + "zod": "^3.22.0 || ^4.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + }, + "zod": { + "optional": true + } + } + }, "node_modules/acorn": { "version": "8.15.0", "dev": true, @@ -818,6 +851,10 @@ "npm": ">=9" } }, + "node_modules/eventemitter3": { + "version": "5.0.1", + "license": "MIT" + }, "node_modules/fsevents": { "version": "2.3.3", "dev": true, @@ -880,6 +917,19 @@ "version": "2.0.4", "license": "ISC" }, + "node_modules/isows": { + "version": "1.0.7", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/wevm" + } + ], + "license": "MIT", + "peerDependencies": { + "ws": "*" + } + }, "node_modules/lodash": { "version": "4.17.21", "license": "MIT" @@ -930,6 +980,97 @@ } } }, + "node_modules/ox": { + "version": "0.11.3", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/wevm" + } + ], + "license": "MIT", + "dependencies": { + "@adraffy/ens-normalize": "^1.11.0", + "@noble/ciphers": "^1.3.0", + "@noble/curves": "1.9.1", + "@noble/hashes": "^1.8.0", + "@scure/bip32": "^1.7.0", + "@scure/bip39": "^1.6.0", + "abitype": "^1.2.3", + "eventemitter3": "5.0.1" + }, + "peerDependencies": { + "typescript": ">=5.4.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/ox/node_modules/@noble/ciphers": { + "version": "1.3.0", + "license": "MIT", + "engines": { + "node": "^14.21.3 || >=16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/ox/node_modules/@noble/curves": { + "version": "1.9.1", + "license": "MIT", + "dependencies": { + "@noble/hashes": "1.8.0" + }, + "engines": { + "node": "^14.21.3 || >=16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/ox/node_modules/@noble/hashes": { + "version": "1.8.0", + "license": "MIT", + "engines": { + "node": "^14.21.3 || >=16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/ox/node_modules/@scure/base": { + "version": "1.2.6", + "license": "MIT", + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/ox/node_modules/@scure/bip32": { + "version": "1.7.0", + "license": "MIT", + "dependencies": { + "@noble/curves": "~1.9.0", + "@noble/hashes": "~1.8.0", + "@scure/base": "~1.2.5" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/ox/node_modules/@scure/bip39": { + "version": "1.6.0", + "license": "MIT", + "dependencies": { + "@noble/hashes": "~1.8.0", + "@scure/base": "~1.2.5" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, "node_modules/resolve-pkg-maps": { "version": "1.0.0", "dev": true, @@ -1004,7 +1145,7 @@ }, "node_modules/typescript": { "version": "5.9.3", - "dev": true, + "devOptional": true, "license": "Apache-2.0", "bin": { "tsc": "bin/tsc", @@ -1024,6 +1165,87 @@ "dev": true, "license": "MIT" }, + "node_modules/viem": { + "version": "2.45.0", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/wevm" + } + ], + "license": "MIT", + "dependencies": { + "@noble/curves": "1.9.1", + "@noble/hashes": "1.8.0", + "@scure/bip32": "1.7.0", + "@scure/bip39": "1.6.0", + "abitype": "1.2.3", + "isows": "1.0.7", + "ox": "0.11.3", + "ws": "8.18.3" + }, + "peerDependencies": { + "typescript": ">=5.0.4" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/viem/node_modules/@noble/curves": { + "version": "1.9.1", + "license": "MIT", + "dependencies": { + "@noble/hashes": "1.8.0" + }, + "engines": { + "node": "^14.21.3 || >=16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/viem/node_modules/@noble/hashes": { + "version": "1.8.0", + "license": "MIT", + "engines": { + "node": "^14.21.3 || >=16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/viem/node_modules/@scure/base": { + "version": "1.2.6", + "license": "MIT", + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/viem/node_modules/@scure/bip32": { + "version": "1.7.0", + "license": "MIT", + "dependencies": { + "@noble/curves": "~1.9.0", + "@noble/hashes": "~1.8.0", + "@scure/base": "~1.2.5" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/viem/node_modules/@scure/bip39": { + "version": "1.6.0", + "license": "MIT", + "dependencies": { + "@noble/hashes": "~1.8.0", + "@scure/base": "~1.2.5" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, "node_modules/webidl-conversions": { "version": "3.0.1", "license": "BSD-2-Clause" @@ -1036,6 +1258,25 @@ "webidl-conversions": "^3.0.0" } }, + "node_modules/ws": { + "version": "8.18.3", + "license": "MIT", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, "node_modules/yn": { "version": "3.1.1", "dev": true, diff --git a/package.json b/package.json index d45c0f9..7bb0447 100644 --- a/package.json +++ b/package.json @@ -6,56 +6,70 @@ "author": "Otniel Nicola", "type": "module", "scripts": { - "amb:serialize": "tsx src/neo/message-bridge/serializeCall.ts", - "amb:execute": "tsx src/neo/message-bridge/executeMessage.ts", - "amb:send-excutable": "MESSAGE_BRIDGE_OPERATION=send-executable tsx src/neo/message-bridge/sendMessage.ts", - "amb:send-result": "MESSAGE_BRIDGE_OPERATION=send-result tsx src/neo/message-bridge/sendMessage.ts", - "amb:send-store-only": "MESSAGE_BRIDGE_OPERATION=send-store-only tsx src/neo/message-bridge/sendMessage.ts", - "amb:set-executor": "tsx src/neo/message-bridge/setExecutionManager.ts", - "amb:readonly": "tsx src/neo/message-bridge/readOnlyMethods.ts", - "amb:pause": "tsx src/neo/message-bridge/performAllPauseOperations.ts", - "em:readonly": "tsx src/neo/execution-manager/readOnlyMethods.ts", - "em:execute": "tsx src/neo/execution-manager/executeMessage.ts", - "em:serialize": "tsx src/neo/execution-manager/serializeCall.ts", - "em:pause": "tsx src/neo/execution-manager/pauseOperations.ts", - "em:serialize-pause": "SERIALIZE_METHOD=isPaused tsx src/neo/execution-manager/serializeCall.ts", - "nb:readonly": "tsx src/neo/native-bridge/readOnlyMethods.ts", - "nb:operations": "tsx src/neo/native-bridge/nativeBridgeOperations.ts", - "nb:pause": "tsx src/neo/native-bridge/pauseOperations.ts", - "nb:set": "NATIVE_OPERATION=set-native-bridge tsx src/neo/native-bridge/nativeBridgeOperations.ts", - "nb:deposit": "NATIVE_OPERATION=deposit-native tsx src/neo/native-bridge/nativeBridgeOperations.ts", - "nb:claim": "NATIVE_OPERATION=claim-native tsx src/neo/native-bridge/nativeBridgeOperations.ts", - "nb:pause-bridge": "NATIVE_OPERATION=pause-native tsx src/neo/native-bridge/nativeBridgeOperations.ts", - "nb:unpause-bridge": "NATIVE_OPERATION=unpause-native tsx src/neo/native-bridge/nativeBridgeOperations.ts", - "nb:set-fee": "NATIVE_OPERATION=set-native-fee tsx src/neo/native-bridge/nativeBridgeOperations.ts", - "nb:set-min": "NATIVE_OPERATION=set-native-min tsx src/neo/native-bridge/nativeBridgeOperations.ts", - "nb:set-max": "NATIVE_OPERATION=set-native-max tsx src/neo/native-bridge/nativeBridgeOperations.ts", - "nb:set-total": "NATIVE_OPERATION=set-native-total tsx src/neo/native-bridge/nativeBridgeOperations.ts", - "tb:readonly": "tsx src/neo/token-bridge/readOnlyMethods.ts", - "tb:operations": "tsx src/neo/token-bridge/tokenBridgeOperations.ts", - "tb:register": "TOKEN_OPERATION=register-token tsx src/neo/token-bridge/tokenBridgeOperations.ts", - "tb:deposit": "TOKEN_OPERATION=deposit-token tsx src/neo/token-bridge/tokenBridgeOperations.ts", - "tb:claim": "TOKEN_OPERATION=claim-token tsx src/neo/token-bridge/tokenBridgeOperations.ts", - "tb:pause": "TOKEN_OPERATION=pause-token tsx src/neo/token-bridge/tokenBridgeOperations.ts", - "tb:unpause": "TOKEN_OPERATION=unpause-token tsx src/neo/token-bridge/tokenBridgeOperations.ts", - "tb:set-fee": "TOKEN_OPERATION=set-token-fee tsx src/neo/token-bridge/tokenBridgeOperations.ts", - "tb:set-min": "TOKEN_OPERATION=set-token-min tsx src/neo/token-bridge/tokenBridgeOperations.ts", - "tb:set-max": "TOKEN_OPERATION=set-token-max tsx src/neo/token-bridge/tokenBridgeOperations.ts", - "tb:set-withdrawals": "TOKEN_OPERATION=set-token-withdrawals tsx src/neo/token-bridge/tokenBridgeOperations.ts", - "mgmt:readonly": "tsx src/neo/management/readOnlyMethods.ts", - "mgmt:validator-add": "VALIDATOR_ACTION=add tsx src/neo/management/validatorManagement.ts", - "mgmt:validator-remove": "VALIDATOR_ACTION=remove tsx src/neo/management/validatorManagement.ts", - "mgmt:validator-replace": "VALIDATOR_ACTION=replace tsx src/neo/management/validatorManagement.ts", - "mgmt:validator-threshold": "VALIDATOR_ACTION=set-threshold tsx src/neo/management/validatorManagement.ts", - "mgmt:set-owner": "MANAGEMENT_ACTION=set-owner tsx src/neo/management/ownerRelayerGovernor.ts", - "mgmt:set-relayer": "MANAGEMENT_ACTION=set-relayer tsx src/neo/management/ownerRelayerGovernor.ts", - "mgmt:set-governor": "MANAGEMENT_ACTION=set-governor tsx src/neo/management/ownerRelayerGovernor.ts", - "mgmt:set-security": "MANAGEMENT_ACTION=set-security-guard tsx src/neo/management/ownerRelayerGovernor.ts", - "wallet": "tsx src/neo/wallet/walletOperations.ts" + "neo:amb:serialize": "tsx src/neo/message-bridge/serializeCall.ts", + "neo:amb:execute": "tsx src/neo/message-bridge/executeMessage.ts", + "neo:amb:send-excutable": "MESSAGE_BRIDGE_OPERATION=send-executable tsx src/neo/message-bridge/sendMessage.ts", + "neo:amb:send-result": "MESSAGE_BRIDGE_OPERATION=send-result tsx src/neo/message-bridge/sendMessage.ts", + "neo:amb:send-store-only": "MESSAGE_BRIDGE_OPERATION=send-store-only tsx src/neo/message-bridge/sendMessage.ts", + "neo:amb:set-executor": "tsx src/neo/message-bridge/setExecutionManager.ts", + "neo:amb:readonly": "tsx src/neo/message-bridge/readOnlyMethods.ts", + "neo:amb:pause": "tsx src/neo/message-bridge/performAllPauseOperations.ts", + "neo:em:readonly": "tsx src/neo/execution-manager/readOnlyMethods.ts", + "neo:em:execute": "tsx src/neo/execution-manager/executeMessage.ts", + "neo:em:serialize": "tsx src/neo/execution-manager/serializeCall.ts", + "neo:em:pause": "tsx src/neo/execution-manager/pauseOperations.ts", + "neo:em:serialize-pause": "SERIALIZE_METHOD=isPaused tsx src/neo/execution-manager/serializeCall.ts", + "neo:nb:readonly": "tsx src/neo/native-bridge/readOnlyMethods.ts", + "neo:nb:operations": "tsx src/neo/native-bridge/nativeBridgeOperations.ts", + "neo:nb:pause": "tsx src/neo/native-bridge/pauseOperations.ts", + "neo:nb:set": "NATIVE_OPERATION=set-native-bridge tsx src/neo/native-bridge/nativeBridgeOperations.ts", + "neo:nb:deposit": "NATIVE_OPERATION=deposit-native tsx src/neo/native-bridge/nativeBridgeOperations.ts", + "neo:nb:claim": "NATIVE_OPERATION=claim-native tsx src/neo/native-bridge/nativeBridgeOperations.ts", + "neo:nb:pause-bridge": "NATIVE_OPERATION=pause-native tsx src/neo/native-bridge/nativeBridgeOperations.ts", + "neo:nb:unpause-bridge": "NATIVE_OPERATION=unpause-native tsx src/neo/native-bridge/nativeBridgeOperations.ts", + "neo:nb:set-fee": "NATIVE_OPERATION=set-native-fee tsx src/neo/native-bridge/nativeBridgeOperations.ts", + "neo:nb:set-min": "NATIVE_OPERATION=set-native-min tsx src/neo/native-bridge/nativeBridgeOperations.ts", + "neo:nb:set-max": "NATIVE_OPERATION=set-native-max tsx src/neo/native-bridge/nativeBridgeOperations.ts", + "neo:nb:set-total": "NATIVE_OPERATION=set-native-total tsx src/neo/native-bridge/nativeBridgeOperations.ts", + "neo:tb:readonly": "tsx src/neo/token-bridge/readOnlyMethods.ts", + "neo:tb:operations": "tsx src/neo/token-bridge/tokenBridgeOperations.ts", + "neo:tb:register": "TOKEN_OPERATION=register-token tsx src/neo/token-bridge/tokenBridgeOperations.ts", + "neo:tb:deposit": "TOKEN_OPERATION=deposit-token tsx src/neo/token-bridge/tokenBridgeOperations.ts", + "neo:tb:claim": "TOKEN_OPERATION=claim-token tsx src/neo/token-bridge/tokenBridgeOperations.ts", + "neo:tb:pause": "TOKEN_OPERATION=pause-token tsx src/neo/token-bridge/tokenBridgeOperations.ts", + "neo:tb:unpause": "TOKEN_OPERATION=unpause-token tsx src/neo/token-bridge/tokenBridgeOperations.ts", + "neo:tb:set-fee": "TOKEN_OPERATION=set-token-fee tsx src/neo/token-bridge/tokenBridgeOperations.ts", + "neo:tb:set-min": "TOKEN_OPERATION=set-token-min tsx src/neo/token-bridge/tokenBridgeOperations.ts", + "neo:tb:set-max": "TOKEN_OPERATION=set-token-max tsx src/neo/token-bridge/tokenBridgeOperations.ts", + "neo:tb:set-withdrawals": "TOKEN_OPERATION=set-token-withdrawals tsx src/neo/token-bridge/tokenBridgeOperations.ts", + "neo:mgmt:readonly": "tsx src/neo/management/readOnlyMethods.ts", + "neo:mgmt:validator-add": "VALIDATOR_ACTION=add tsx src/neo/management/validatorManagement.ts", + "neo:mgmt:validator-remove": "VALIDATOR_ACTION=remove tsx src/neo/management/validatorManagement.ts", + "neo:mgmt:validator-replace": "VALIDATOR_ACTION=replace tsx src/neo/management/validatorManagement.ts", + "neo:mgmt:validator-threshold": "VALIDATOR_ACTION=set-threshold tsx src/neo/management/validatorManagement.ts", + "neo:mgmt:set-owner": "MANAGEMENT_ACTION=set-owner tsx src/neo/management/ownerRelayerGovernor.ts", + "neo:mgmt:set-relayer": "MANAGEMENT_ACTION=set-relayer tsx src/neo/management/ownerRelayerGovernor.ts", + "neo:mgmt:set-governor": "MANAGEMENT_ACTION=set-governor tsx src/neo/management/ownerRelayerGovernor.ts", + "neo:mgmt:set-security": "MANAGEMENT_ACTION=set-security-guard tsx src/neo/management/ownerRelayerGovernor.ts", + "neo:wallet": "tsx src/neo/wallet/walletOperations.ts", + "evm:amb:execute": "tsx src/evm/message-bridge/executeMessage.ts", + "evm:amb:readonly": "tsx src/evm/message-bridge/readOnlyMethods.ts", + "evm:amb:pause": "tsx src/evm/message-bridge/pauseOperations.ts", + "evm:amb:send-executable": "MESSAGE_BRIDGE_OPERATION=send-executable tsx src/evm/message-bridge/sendMessage.ts", + "evm:amb:send-result": "MESSAGE_BRIDGE_OPERATION=send-result tsx src/evm/message-bridge/sendMessage.ts", + "evm:amb:send-store-only": "MESSAGE_BRIDGE_OPERATION=send-store-only tsx src/evm/message-bridge/sendMessage.ts", + "evm:amb:set-executor": "tsx src/evm/message-bridge/setExecutionManager.ts", + "evm:em:execute": "tsx src/evm/execution-manager/executeMessage.ts", + "evm:em:readonly": "tsx src/evm/execution-manager/readOnlyMethods.ts", + "evm:nb:readonly": "tsx src/evm/native-bridge/readOnlyMethods.ts", + "evm:tb:readonly": "tsx src/evm/token-bridge/readOnlyMethods.ts", + "evm:mgmt:readonly": "tsx src/evm/bridge-management/readOnlyMethods.ts", + "evm:wallet": "tsx src/evm/wallet/walletOperations.ts" }, "dependencies": { - "@bane-labs/bridge-sdk-ts": "^1.0.0-beta.6", - "dotenv": "^17.2.3" + "@bane-labs/bridge-sdk-ts": "file:../../../bridge-sdk-ts/bane-labs-bridge-sdk-ts-1.0.0-beta.7.tgz", + "dotenv": "^17.2.3", + "viem": "^2.21.53" }, "devDependencies": { "@types/node": "^24.10.1", diff --git a/src/evm/README.md b/src/evm/README.md new file mode 100644 index 0000000..6a79de1 --- /dev/null +++ b/src/evm/README.md @@ -0,0 +1,78 @@ +# EVM Bridge Examples + +This directory contains TypeScript examples for interacting with the EVM side of the bridge using the `@bane-labs/bridge-sdk-ts` package. + +## Structure + +- **`message-bridge/`** - Examples for cross-chain message bridging operations +- **`execution-manager/`** - Examples for message execution and management +- **`native-bridge/`** - Examples for native token bridging operations +- **`token-bridge/`** - Examples for ERC-20 token bridging operations +- **`bridge-management/`** - Examples for governance and validator management +- **`wallet/`** - Basic wallet operation examples +- **`utils.ts`** - Utility functions for creating contract instances + +## Getting Started + +### Prerequisites + +1. Node.js and npm installed +2. Access to an EVM-compatible network (local or testnet) +3. A funded wallet for transaction operations + +### Environment Variables + +Create a `.env` file in the project root with the following variables: + +```env +# EVM Network Configuration +EVM_RPC_URL=http://localhost:8545 +EVM_PRIVATE_KEY=0x... + +# Contract Addresses +EVM_MESSAGE_BRIDGE_CONTRACT_ADDRESS=0x... +EVM_EXECUTION_MANAGER_CONTRACT_ADDRESS=0x... +EVM_NATIVE_BRIDGE_CONTRACT_ADDRESS=0x... +EVM_TOKEN_BRIDGE_CONTRACT_ADDRESS=0x... +EVM_BRIDGE_MANAGEMENT_CONTRACT_ADDRESS=0x... + +# Optional: For testing specific operations +MESSAGE_NONCE=1 +MESSAGE_EXECUTABLE_DATA=0x... +TOKEN_ADDRESS=0x... +VALIDATOR_ADDRESS=0x... +``` + +### Running Examples + +All examples can be run using npm scripts. The naming convention is: +``` +npm run evm:: +``` + +For example: +- `npm run evm:amb:readonly` - Read message bridge state +- `npm run evm:em:execute` - Execute a message +- `npm run evm:nb:readonly` - Read native bridge state + +See individual README files in each subdirectory for more specific examples and required environment variables. + +## Key Differences from NEO Examples + +1. **Address Format**: Uses checksummed Ethereum addresses (0x...) instead of Neo addresses +2. **Value Units**: Uses wei for native token amounts instead of GAS units +3. **Transaction Format**: Uses Ethereum transaction hashes and receipts +4. **Client Setup**: Uses viem's PublicClient/WalletClient instead of Neo's RpcClient/Account +5. **Contract Interaction**: Uses read/write pattern typical of Ethereum contract interactions + +## Contract Interactions + +### Read-Only Operations +Read-only operations only require `EVM_RPC_URL` and contract addresses. They use the `read` property of contract instances. + +### Write Operations +Write operations require `EVM_PRIVATE_KEY` in addition to read requirements. They use the `write` property and return transaction hashes. + +## Error Handling + +All examples include proper error handling and will exit with status code 1 on failure. Check console output for detailed error messages. diff --git a/src/evm/bridge-management/README.md b/src/evm/bridge-management/README.md new file mode 100644 index 0000000..1450ff0 --- /dev/null +++ b/src/evm/bridge-management/README.md @@ -0,0 +1,31 @@ +# EVM Bridge Management Examples + +This directory contains examples for interacting with the EVM Bridge Management contract, which handles governance and configuration operations. + +## Files + +- `validatorManagement.ts` - Validator management operations (add, remove, replace, set threshold) +- `ownerRelayerGovernor.ts` - Owner, relayer, and governor management operations +- `readOnlyMethods.ts` - Read-only method calls to query bridge management state + +## Available Scripts + +### Bridge Management Operations +- `npm run evm:mgmt:readonly` - Read all bridge management state information +- `npm run evm:mgmt:validator-add` - Add a new validator +- `npm run evm:mgmt:validator-remove` - Remove a validator +- `npm run evm:mgmt:validator-replace` - Replace an existing validator +- `npm run evm:mgmt:validator-threshold` - Set validator threshold +- `npm run evm:mgmt:set-owner` - Set contract owner +- `npm run evm:mgmt:set-relayer` - Set relayer address +- `npm run evm:mgmt:set-governor` - Set governor address + +## Required Environment Variables + +- `EVM_BRIDGE_MANAGEMENT_CONTRACT_ADDRESS` - Contract address of the EVM Bridge Management +- `EVM_RPC_URL` - RPC URL of the EVM node (defaults to http://localhost:8545) +- `EVM_PRIVATE_KEY` - Private key for the wallet (required for write operations) + +### Operation-specific Variables +- For validator operations: `VALIDATOR_ADDRESS`, `NEW_VALIDATOR_ADDRESS`, `VALIDATOR_THRESHOLD` +- For role operations: `OWNER_ADDRESS`, `RELAYER_ADDRESS`, `GOVERNOR_ADDRESS` diff --git a/src/evm/bridge-management/readOnlyMethods.ts b/src/evm/bridge-management/readOnlyMethods.ts new file mode 100644 index 0000000..7478cb6 --- /dev/null +++ b/src/evm/bridge-management/readOnlyMethods.ts @@ -0,0 +1,57 @@ +import { EvmBridgeManagement } from "@bane-labs/bridge-sdk-ts"; +import { ensureEnv } from "../utils"; + +export async function callReadOnlyMethods(bridgeManagement: EvmBridgeManagement) { + console.log("\n--- Testing EVM Bridge Management Read-Only Methods ---"); + + try { + const owner = await bridgeManagement.owner(); + console.log(`Owner: ${owner}`); + + const relayer = await bridgeManagement.getRelayer(); + console.log(`Relayer: ${relayer}`); + + const governor = await bridgeManagement.getGovernor(); + console.log(`Governor: ${governor}`); + + const validators = await bridgeManagement.getValidators(); + console.log(`Validator Count: ${validators.length}`); + + const threshold = await bridgeManagement.getValidatorThreshold(); + console.log(`Validator Threshold: ${threshold}`); + + console.log("\nValidators:"); + for (let i = 0n; i < validators.length; i++) { + console.log(` Validator ${i}: ${validators[Number(i)]}`); + } + + const testValidatorAddress = process.env.VALIDATOR_ADDRESS as `0x${string}`; + if (testValidatorAddress) { + const isValidator = await bridgeManagement.isValidator(testValidatorAddress); + console.log(`Is Validator (${testValidatorAddress}): ${isValidator}`); + } + + console.log("\n--- EVM Bridge Management Read-Only Methods Completed Successfully ---"); + } catch (error) { + console.error("Error calling read-only methods:", error); + throw error; + } +} + +async function main() { + ensureEnv(); + + const { createBridgeManagementFromEnvironment } = await import("../utils"); + + try { + const bridgeManagement = createBridgeManagementFromEnvironment(); + await callReadOnlyMethods(bridgeManagement); + } catch (error) { + console.error("Failed to test EVM Bridge Management read-only methods:", error); + process.exit(1); + } +} + +if (import.meta.url === `file://${process.argv[1]}`) { + main().catch(console.error); +} diff --git a/src/evm/execution-manager/README.md b/src/evm/execution-manager/README.md new file mode 100644 index 0000000..0221999 --- /dev/null +++ b/src/evm/execution-manager/README.md @@ -0,0 +1,26 @@ +# EVM Execution Manager Examples + +This directory contains examples for interacting with the EVM ExecutionManager contract, which handles message execution and access control operations. + +## Files + +- `executeMessage.ts` - Execute messages with specified nonce and executable code +- `readOnlyMethods.ts` - Read-only method calls to query execution manager state + +## Available Scripts + +### Execution Manager Operations +- `npm run evm:em:execute` - Execute a message using MESSAGE_NONCE and EXECUTABLE_CODE +- `npm run evm:em:readonly` - Read all execution manager state information + +## Required Environment Variables + +- `EVM_EXECUTION_MANAGER_CONTRACT_ADDRESS` - Contract address of the EVM ExecutionManager +- `EVM_RPC_URL` - RPC URL of the EVM node (defaults to http://localhost:8545) +- `EVM_PRIVATE_KEY` - Private key for the wallet (required for write operations) + +### Operation-specific Variables +- For `executeMessage.ts`: + - `MESSAGE_NONCE` (integer) - The nonce of the message to execute + - `EXECUTABLE_CODE` (hex string) - The executable code/data to process + - `REFUND_ADDRESS` or `EVM_WALLET_ADDRESS` (address) - Address to refund any excess gas to diff --git a/src/evm/execution-manager/executeMessage.ts b/src/evm/execution-manager/executeMessage.ts new file mode 100644 index 0000000..54d57a1 --- /dev/null +++ b/src/evm/execution-manager/executeMessage.ts @@ -0,0 +1,55 @@ +import { EvmExecutionManager } from "@bane-labs/bridge-sdk-ts"; +import { createExecutionManagerFromEnvironment, ensureEnv, requireEnvVar } from "../utils"; + +async function executeMessage(executionManager: EvmExecutionManager, nonce: bigint, executableCode: string, refundAddress: string) { + console.log(`Executing message with nonce: ${nonce}`); + console.log(`Executable code: ${executableCode}`); + console.log(`Refund address: ${refundAddress}`); + + try { + const hash = await executionManager.executeMessage( + nonce, + executableCode as `0x${string}`, + refundAddress as `0x${string}` + ); + + console.log(`Message executed successfully. Transaction hash: ${hash}`); + return hash; + } catch (error) { + console.error(`Failed to execute message with nonce ${nonce}:`, error); + throw error; + } +} + +async function main() { + ensureEnv(); + + try { + const executionManager = createExecutionManagerFromEnvironment(); + + if (!process.env.EVM_PRIVATE_KEY) { + throw new Error('Wallet client is required for write operations. Please set EVM_PRIVATE_KEY environment variable.'); + } + + const nonceStr = requireEnvVar('MESSAGE_NONCE'); + const executableCode = requireEnvVar('EXECUTABLE_CODE'); + const refundAddress = process.env.REFUND_ADDRESS || process.env.EVM_WALLET_ADDRESS; + + if (!refundAddress) { + throw new Error('REFUND_ADDRESS or EVM_WALLET_ADDRESS environment variable is required'); + } + + const nonce = BigInt(nonceStr); + + await executeMessage(executionManager, nonce, executableCode, refundAddress); + + console.log('\nMessage execution completed successfully!'); + } catch (error) { + console.error('Failed to execute message:', error); + process.exit(1); + } +} + +if (import.meta.url === `file://${process.argv[1]}`) { + main().catch(console.error); +} diff --git a/src/evm/execution-manager/readOnlyMethods.ts b/src/evm/execution-manager/readOnlyMethods.ts new file mode 100644 index 0000000..d84a136 --- /dev/null +++ b/src/evm/execution-manager/readOnlyMethods.ts @@ -0,0 +1,43 @@ +import { EvmExecutionManager } from "@bane-labs/bridge-sdk-ts"; +import { ensureEnv } from "../utils"; + +export async function callReadOnlyMethods(executionManager: EvmExecutionManager) { + console.log("\n--- Testing EVM Execution Manager Read-Only Methods ---"); + + try { + const version = await executionManager.VERSION(); + console.log(`Contract Version: ${version}`); + + const executingNonce = await executionManager.executingNonce(); + console.log(`Executing Nonce: ${executingNonce}`); + + const defaultAdminRole = await executionManager.DEFAULT_ADMIN_ROLE(); + console.log(`Default Admin Role: ${defaultAdminRole}`); + + const bridgeRole = await executionManager.BRIDGE_ROLE(); + console.log(`Bridge Role: ${bridgeRole}`); + + console.log("\n--- EVM Execution Manager Read-Only Methods Completed Successfully ---"); + } catch (error) { + console.error("Error calling read-only methods:", error); + throw error; + } +} + +async function main() { + ensureEnv(); + + const { createExecutionManagerFromEnvironment } = await import("../utils"); + + try { + const executionManager = createExecutionManagerFromEnvironment(); + await callReadOnlyMethods(executionManager); + } catch (error) { + console.error("Failed to test EVM Execution Manager read-only methods:", error); + process.exit(1); + } +} + +if (import.meta.url === `file://${process.argv[1]}`) { + main().catch(console.error); +} diff --git a/src/evm/message-bridge/README.md b/src/evm/message-bridge/README.md new file mode 100644 index 0000000..34acd22 --- /dev/null +++ b/src/evm/message-bridge/README.md @@ -0,0 +1,34 @@ +# EVM Message Bridge Examples + +This directory contains examples for interacting with the EVM Message Bridge contract, which handles cross-chain message bridging operations between EVM and Neo. + +## Files + +- `executeMessage.ts` - Execute messages with specified nonce +- `pauseOperations.ts` - Test pause/unpause operations for sending and executing +- `readOnlyMethods.ts` - Read-only method calls to query message bridge state +- `sendMessage.ts` - Send executable, result, or store-only messages +- `setExecutionManager.ts` - Set the execution manager address + +## Available Scripts + +### Message Bridge Operations +- `npm run evm:amb:execute` - Execute a message using MESSAGE_NONCE +- `npm run evm:amb:readonly` - Read all message bridge state information +- `npm run evm:amb:pause` - Test all pause/unpause operations +- `npm run evm:amb:send-executable` - Send an executable message +- `npm run evm:amb:send-result` - Send a result message +- `npm run evm:amb:send-store-only` - Send a store-only message +- `npm run evm:amb:set-executor` - Set execution manager address + +## Required Environment Variables + +- `EVM_MESSAGE_BRIDGE_CONTRACT_ADDRESS` - Contract address of the EVM Message Bridge +- `EVM_RPC_URL` - RPC URL of the EVM node (defaults to http://localhost:8545) +- `EVM_PRIVATE_KEY` - Private key for the wallet (required for write operations) + +### Operation-specific Variables +- For `sendMessage.ts`: `MESSAGE_BRIDGE_OPERATION` (send-executable, send-result, send-store-only), `MESSAGE_EXECUTABLE_DATA`, `MESSAGE_STORE_RESULT` (boolean), `MESSAGE_NONCE` (for result), `MESSAGE_STORE_ONLY_DATA` +- For `executeMessage.ts`: `MESSAGE_NONCE` (integer) +- For `setExecutionManager.ts`: `EXECUTION_MANAGER_ADDRESS` +- For `readOnlyMethods.ts`: Optional `MESSAGE_NONCE` (integer, defaults to 1 for testing) diff --git a/src/evm/message-bridge/executeMessage.ts b/src/evm/message-bridge/executeMessage.ts new file mode 100644 index 0000000..7beec17 --- /dev/null +++ b/src/evm/message-bridge/executeMessage.ts @@ -0,0 +1,55 @@ +import { EvmMessageBridge } from "@bane-labs/bridge-sdk-ts"; +import { createMessageBridgeFromEnvironment, ensureEnv, requireEnvVar } from "../utils"; + +async function executeMessage(messageBridge: EvmMessageBridge, nonce: bigint) { + console.log(`Executing message with nonce: ${nonce}`); + + try { + const executableState = await messageBridge.getEvmExecutableState(nonce); + + if (executableState.executed) { + console.log(`Message with nonce ${nonce} has already been executed`); + return; + } + + const currentTime = BigInt(Math.floor(Date.now() / 1000)); + if (executableState.expirationTimestamp < currentTime) { + console.log(`Message with nonce ${nonce} has expired (expiration: ${executableState.expirationTimestamp}, current: ${currentTime})`); + return; + } + + const hash = await messageBridge.executeMessage(nonce); + console.log(`Message executed successfully. Transaction hash: ${hash}`); + + return hash; + } catch (error) { + console.error(`Failed to execute message with nonce ${nonce}:`, error); + throw error; + } +} + +async function main() { + ensureEnv(); + + try { + const messageBridge = createMessageBridgeFromEnvironment(); + + if (!process.env.EVM_PRIVATE_KEY) { + throw new Error('Wallet client is required for write operations. Please set EVM_PRIVATE_KEY environment variable.'); + } + + const nonceStr = requireEnvVar('MESSAGE_NONCE'); + const nonce = BigInt(nonceStr); + + await executeMessage(messageBridge, nonce); + + console.log('\nMessage execution completed successfully!'); + } catch (error) { + console.error('Failed to execute message:', error); + process.exit(1); + } +} + +if (import.meta.url === `file://${process.argv[1]}`) { + main().catch(console.error); +} diff --git a/src/evm/message-bridge/pauseOperations.ts b/src/evm/message-bridge/pauseOperations.ts new file mode 100644 index 0000000..0488af3 --- /dev/null +++ b/src/evm/message-bridge/pauseOperations.ts @@ -0,0 +1,81 @@ +import { EvmMessageBridge } from "@bane-labs/bridge-sdk-ts"; +import { createMessageBridgeFromEnvironment, ensureEnv } from "../utils"; + +async function testPauseOperations(messageBridge: EvmMessageBridge) { + console.log("\n--- Testing EVM Message Bridge Pause Operations ---"); + + try { + console.log("\n1. Checking initial pause states..."); + const isSendingPaused = await messageBridge.sendingPaused(); + const isExecutingPaused = await messageBridge.executingPaused(); + console.log(`Initial - Sending Paused: ${isSendingPaused}, Executing Paused: ${isExecutingPaused}`); + + console.log("\n2. Testing pause sending..."); + if (!isSendingPaused) { + const hash = await messageBridge.pauseSending(); + console.log(`Pause sending transaction hash: ${hash}`); + } else { + console.log("Sending is already paused"); + } + + console.log("\n3. Testing pause executing..."); + if (!isExecutingPaused) { + const hash = await messageBridge.pauseExecuting(); + console.log(`Pause executing transaction hash: ${hash}`); + } else { + console.log("Executing is already paused"); + } + + console.log("\n4. Checking pause states after pausing..."); + const sendingPausedAfter = await messageBridge.sendingPaused(); + const executingPausedAfter = await messageBridge.executingPaused(); + console.log(`After pausing - Sending Paused: ${sendingPausedAfter}, Executing Paused: ${executingPausedAfter}`); + + console.log("\n5. Testing unpause sending..."); + if (sendingPausedAfter) { + const hash = await messageBridge.unpauseSending(); + console.log(`Unpause sending transaction hash: ${hash}`); + } else { + console.log("Sending is not paused"); + } + + console.log("\n6. Testing unpause executing..."); + if (executingPausedAfter) { + const hash = await messageBridge.unpauseExecuting(); + console.log(`Unpause executing transaction hash: ${hash}`); + } else { + console.log("Executing is not paused"); + } + + console.log("\n7. Checking final pause states..."); + const finalSendingPaused = await messageBridge.sendingPaused(); + const finalExecutingPaused = await messageBridge.executingPaused(); + console.log(`Final - Sending Paused: ${finalSendingPaused}, Executing Paused: ${finalExecutingPaused}`); + + console.log("\n--- EVM Message Bridge Pause Operations Completed Successfully ---"); + } catch (error) { + console.error("Error testing pause operations:", error); + throw error; + } +} + +async function main() { + ensureEnv(); + + try { + const messageBridge = createMessageBridgeFromEnvironment(); + + if (!process.env.EVM_PRIVATE_KEY) { + throw new Error('Wallet client is required for write operations. Please set EVM_PRIVATE_KEY environment variable.'); + } + + await testPauseOperations(messageBridge); + } catch (error) { + console.error('Failed to test EVM Message Bridge pause operations:', error); + process.exit(1); + } +} + +if (import.meta.url === `file://${process.argv[1]}`) { + main().catch(console.error); +} diff --git a/src/evm/message-bridge/readOnlyMethods.ts b/src/evm/message-bridge/readOnlyMethods.ts new file mode 100644 index 0000000..df5795c --- /dev/null +++ b/src/evm/message-bridge/readOnlyMethods.ts @@ -0,0 +1,70 @@ +import { EvmMessageBridge } from "@bane-labs/bridge-sdk-ts"; +import { ensureEnv } from "../utils"; + +export async function callReadOnlyMethods(messageBridge: EvmMessageBridge) { + console.log("\n--- Testing EVM Message Bridge Read-Only Methods ---"); + + try { + const sendingFee = await messageBridge.sendingFee(); + console.log(`Sending Fee: ${sendingFee} wei`); + + const managementAddress = await messageBridge.management(); + console.log(`Management Contract Address: ${managementAddress}`); + + const unclaimedFees = await messageBridge.unclaimedFees(); + console.log(`Unclaimed Fees: ${unclaimedFees} wei`); + + const executionManagerAddress = await messageBridge.executionManager(); + console.log(`Execution Manager Address: ${executionManagerAddress}`); + + const evmToNeoState = await messageBridge.evmToNeoState(); + console.log(`EVM to Neo State: nonce=${evmToNeoState.nonce}, root=${evmToNeoState.root}`); + + const neoToEvmState = await messageBridge.neoToEvmState(); + console.log(`Neo to EVM State: nonce=${neoToEvmState.nonce}, root=${neoToEvmState.root}`); + + const isSendingPaused = await messageBridge.sendingPaused(); + console.log(`Is Sending Paused: ${isSendingPaused}`); + + const isExecutingPaused = await messageBridge.executingPaused(); + console.log(`Is Executing Paused: ${isExecutingPaused}`); + + const messageNonce = process.env.MESSAGE_NONCE ? BigInt(process.env.MESSAGE_NONCE) : 1n; + + const executableState = await messageBridge.getEvmExecutableState(messageNonce); + console.log(`Executable State for nonce ${messageNonce}: executed=${executableState.executed}, expiration=${executableState.expirationTimestamp}`); + + try { + const messageData = await messageBridge.getEvmMessage(messageNonce); + console.log(`Message Data for nonce ${messageNonce}:`, { + encodedMetadata: messageData.encodedMetadata, + rawMessage: messageData.rawMessage + }); + } catch (error) { + console.log(`No message found for nonce ${messageNonce}`); + } + + console.log("\n--- EVM Message Bridge Read-Only Methods Completed Successfully ---"); + } catch (error) { + console.error("Error calling read-only methods:", error); + throw error; + } +} + +async function main() { + ensureEnv(); + + const { createMessageBridgeFromEnvironment } = await import("../utils"); + + try { + const messageBridge = createMessageBridgeFromEnvironment(); + await callReadOnlyMethods(messageBridge); + } catch (error) { + console.error("Failed to test EVM Message Bridge read-only methods:", error); + process.exit(1); + } +} + +if (import.meta.url === `file://${process.argv[1]}`) { + main().catch(console.error); +} diff --git a/src/evm/message-bridge/sendMessage.ts b/src/evm/message-bridge/sendMessage.ts new file mode 100644 index 0000000..a2a4ac5 --- /dev/null +++ b/src/evm/message-bridge/sendMessage.ts @@ -0,0 +1,100 @@ +import { EvmMessageBridge } from "@bane-labs/bridge-sdk-ts"; +import { createMessageBridgeFromEnvironment, ensureEnv, requireEnvVar } from "../utils"; + +async function sendExecutableMessage(messageBridge: EvmMessageBridge) { + const messageData = requireEnvVar('MESSAGE_EXECUTABLE_DATA'); + const storeResult = process.env.MESSAGE_STORE_RESULT === 'true'; + + console.log(`Sending executable message with data: ${messageData}, storeResult: ${storeResult}`); + + const sendingFee = await messageBridge.sendingFee(); + console.log(`Sending fee: ${sendingFee} wei`); + + const hash = await messageBridge.sendExecutableMessage( + messageData as `0x${string}`, + storeResult, + // { + // value: sendingFee + // } + ); + + console.log('Executable message sent successfully. Transaction hash:', hash); + return hash; +} + +async function sendResultMessage(messageBridge: EvmMessageBridge) { + const nonceStr = requireEnvVar('MESSAGE_NONCE'); + const nonce = BigInt(nonceStr); + + console.log(`Sending result message for nonce: ${nonce}`); + + const sendingFee = await messageBridge.sendingFee(); + console.log(`Sending fee: ${sendingFee} wei`); + + const hash = await messageBridge.sendResultMessage(nonce, + // { + // value: sendingFee + // } + ); + + console.log('Result message sent successfully. Transaction hash:', hash); + return hash; +} + +async function sendStoreOnlyMessage(messageBridge: EvmMessageBridge) { + const messageData = requireEnvVar('MESSAGE_STORE_ONLY_DATA'); + + console.log(`Sending store-only message with data: ${messageData}`); + + const sendingFee = await messageBridge.sendingFee(); + console.log(`Sending fee: ${sendingFee} wei`); + + const hash = await messageBridge.sendStoreOnlyMessage(messageData as `0x${string}`, + // { + // value: sendingFee + // } + ); + + console.log('Store-only message sent successfully. Transaction hash:', hash); + return hash; +} + +async function main() { + ensureEnv(); + + try { + const messageBridge = createMessageBridgeFromEnvironment(); + + if (!process.env.EVM_PRIVATE_KEY) { + throw new Error('Wallet client is required for write operations. Please set EVM_PRIVATE_KEY environment variable.'); + } + + const operation = process.env.MESSAGE_BRIDGE_OPERATION; + + switch (operation) { + case 'send-executable': + await sendExecutableMessage(messageBridge); + break; + case 'send-result': + await sendResultMessage(messageBridge); + break; + case 'send-store-only': + await sendStoreOnlyMessage(messageBridge); + break; + default: + console.log('No valid MESSAGE_BRIDGE_OPERATION specified.'); + console.log('Available operations: send-executable, send-result, send-store-only'); + console.log('Set MESSAGE_BRIDGE_OPERATION environment variable to one of the above values.'); + process.exit(1); + } + + console.log('\nMessage bridge operation completed successfully!'); + } catch (error) { + console.error('Failed to perform message bridge operation:', error); + process.exit(1); + } +} + +if (import.meta.url === `file://${process.argv[1]}`) { + main().catch(console.error); +} diff --git a/src/evm/message-bridge/setExecutionManager.ts b/src/evm/message-bridge/setExecutionManager.ts new file mode 100644 index 0000000..82d662a --- /dev/null +++ b/src/evm/message-bridge/setExecutionManager.ts @@ -0,0 +1,50 @@ +import { EvmMessageBridge } from "@bane-labs/bridge-sdk-ts"; +import { createMessageBridgeFromEnvironment, ensureEnv, requireEnvVar } from "../utils"; + +async function setExecutionManager(messageBridge: EvmMessageBridge, executionManagerAddress: string) { + console.log(`Setting execution manager address to: ${executionManagerAddress}`); + + try { + const currentAddress = await messageBridge.executionManager(); + console.log(`Current execution manager address: ${currentAddress}`); + + if (currentAddress.toLowerCase() === executionManagerAddress.toLowerCase()) { + console.log('The execution manager address is already set to the specified value'); + return; + } + + const hash = await messageBridge.setExecutionManager(executionManagerAddress as `0x${string}`); + console.log(`Set execution manager transaction hash: ${hash}`); + + console.log('Execution manager address updated successfully'); + return hash; + } catch (error) { + console.error('Failed to set execution manager address:', error); + throw error; + } +} + +async function main() { + ensureEnv(); + + try { + const messageBridge = createMessageBridgeFromEnvironment(); + + if (!process.env.EVM_PRIVATE_KEY) { + throw new Error('Wallet client is required for write operations. Please set EVM_PRIVATE_KEY environment variable.'); + } + + const executionManagerAddress = requireEnvVar('EXECUTION_MANAGER_ADDRESS'); + + await setExecutionManager(messageBridge, executionManagerAddress); + + console.log('\nExecution manager setup completed successfully!'); + } catch (error) { + console.error('Failed to set execution manager:', error); + process.exit(1); + } +} + +if (import.meta.url === `file://${process.argv[1]}`) { + main().catch(console.error); +} diff --git a/src/evm/native-bridge/README.md b/src/evm/native-bridge/README.md new file mode 100644 index 0000000..c461c83 --- /dev/null +++ b/src/evm/native-bridge/README.md @@ -0,0 +1,49 @@ +# EVM Native Bridge Examples + +This directory contains examples for interacting with the EVM Native Bridge contract, which handles native token bridging operations between EVM and Neo. + +## Files + +- `readOnlyMethods.ts` - Read-only method calls to query native bridge state and configuration + +## Available Scripts + +### Native Bridge Operations +- `npm run evm:nb:readonly` - Read all native bridge state information + +## Required Environment Variables + +- `EVM_NATIVE_BRIDGE_CONTRACT_ADDRESS` - Contract address of the EVM Native Bridge +- `EVM_RPC_URL` - RPC URL of the EVM node (defaults to http://localhost:8545) +- `EVM_PRIVATE_KEY` - Private key for the wallet (required for write operations) + +### Optional Environment Variables for Testing +- `NATIVE_CLAIM_NONCE` - Nonce to check for claimable native tokens (defaults to 1) + +## Available Information + +The read-only methods provide access to: + +### Bridge Status +- Bridge setup status (`nativeBridgeIsSet()`) +- Bridge pause status (`bridgePaused`) +- Native bridge specific pause status +- Management contract address +- Unclaimed rewards + +### Native Bridge Configuration +- Fee amount (withdrawal fee) +- Minimum and maximum withdrawal amounts +- Maximum number of deposits allowed +- Decimal scaling factor for cross-chain compatibility + +### State Information +- Deposit state (EVM to Neo): current nonce and merkle root +- Withdrawal state (Neo to EVM): current nonce and merkle root +- Claimable native tokens for specific nonces + +### Usage Notes + +- If the native bridge is not set up (`nativeBridgeIsSet()` returns false), only basic bridge information will be available +- The native bridge struct contains comprehensive configuration and state information +- Claimable tokens can be queried by nonce, but will return empty results if no tokens are claimable for that nonce diff --git a/src/evm/native-bridge/readOnlyMethods.ts b/src/evm/native-bridge/readOnlyMethods.ts new file mode 100644 index 0000000..b7b267c --- /dev/null +++ b/src/evm/native-bridge/readOnlyMethods.ts @@ -0,0 +1,83 @@ +import { EvmNativeBridge } from "@bane-labs/bridge-sdk-ts"; +import { ensureEnv } from "../utils"; + +export async function callReadOnlyMethods(nativeBridge: EvmNativeBridge) { + console.log("\n--- Testing EVM Native Bridge Read-Only Methods ---"); + + try { + // Check if native bridge is set up + const isNativeBridgeSet = await nativeBridge.nativeBridgeIsSet(); + console.log(`Native Bridge Is Set: ${isNativeBridgeSet}`); + + if (!isNativeBridgeSet) { + console.log("Native bridge is not set up yet. Limited information available."); + return; + } + + // Get management contract address + const managementAddress = await nativeBridge.management(); + console.log(`Management Contract Address: ${managementAddress}`); + + // Get bridge pause status + const bridgePaused = await nativeBridge.bridgePaused(); + console.log(`Bridge Paused: ${bridgePaused}`); + + // Get native bridge struct which contains config and state + const nativeBridgeStruct = await nativeBridge.nativeBridge(); + const [paused, depositState, withdrawalState, config] = nativeBridgeStruct; + + console.log(`Native Bridge Paused: ${paused}`); + console.log(`Fee: ${config.fee} wei`); + console.log(`Minimum Amount: ${config.minAmount} wei`); + console.log(`Maximum Amount: ${config.maxAmount} wei`); + console.log(`Max Deposits: ${config.maxDeposits}`); + console.log(`Decimal Scaling Factor: ${config.decimalScalingFactor}`); + + // Get deposit state (EVM to Neo) + console.log(`Deposit State - Nonce: ${depositState.nonce}`); + console.log(`Deposit State - Root: ${depositState.root}`); + + // Get withdrawal state (Neo to EVM) + console.log(`Withdrawal State - Nonce: ${withdrawalState.nonce}`); + console.log(`Withdrawal State - Root: ${withdrawalState.root}`); + + // Get unclaimed rewards + const unclaimedRewards = await nativeBridge.unclaimedRewards(); + console.log(`Unclaimed Rewards: ${unclaimedRewards} wei`); + + // Test claimable native for a specific nonce + const testNonce = process.env.NATIVE_CLAIM_NONCE ? BigInt(process.env.NATIVE_CLAIM_NONCE) : 1n; + try { + const claimable = await nativeBridge.claimableNative(testNonce); + const [to, amount] = claimable; + console.log(`Claimable for nonce ${testNonce}:`); + console.log(` - To: ${to}`); + console.log(` - Amount: ${amount} wei`); + } catch (error) { + console.log(`No claimable found for nonce ${testNonce} (this is normal if nothing is claimable)`); + } + + console.log("\n--- EVM Native Bridge Read-Only Methods Completed Successfully ---"); + } catch (error) { + console.error("Error calling read-only methods:", error); + throw error; + } +} + +async function main() { + ensureEnv(); + + const { createNativeBridgeFromEnvironment } = await import("../utils"); + + try { + const nativeBridge = createNativeBridgeFromEnvironment(); + await callReadOnlyMethods(nativeBridge); + } catch (error) { + console.error("Failed to test EVM Native Bridge read-only methods:", error); + process.exit(1); + } +} + +if (import.meta.url === `file://${process.argv[1]}`) { + main().catch(console.error); +} diff --git a/src/evm/token-bridge/README.md b/src/evm/token-bridge/README.md new file mode 100644 index 0000000..7f53aa5 --- /dev/null +++ b/src/evm/token-bridge/README.md @@ -0,0 +1,58 @@ +# EVM Token Bridge Examples + +This directory contains examples for interacting with the EVM Token Bridge contract, which handles token bridging operations between EVM and Neo. + +## Files + +- `readOnlyMethods.ts` - Read-only method calls to query token bridge state and configuration + +## Available Scripts + +### Token Bridge Operations +- `npm run evm:tb:readonly` - Read all token bridge state information + +## Required Environment Variables + +- `EVM_TOKEN_BRIDGE_CONTRACT_ADDRESS` - Contract address of the EVM Token Bridge +- `EVM_RPC_URL` - RPC URL of the EVM node (defaults to http://localhost:8545) +- `EVM_PRIVATE_KEY` - Private key for the wallet (required for write operations) + +### Optional Environment Variables for Testing +- `TOKEN_ADDRESS` - Specific EVM token address to query detailed information for +- `TOKEN_CLAIM_NONCE` - Nonce to check for claimable tokens (defaults to 1) + +## Available Information + +The read-only methods provide access to: + +### Bridge Status +- Bridge pause status (`bridgePaused`) +- Management contract address +- List of all registered tokens +- Unclaimed rewards + +### Token Registration +- Check if a specific token is registered (`isRegisteredToken()`) +- Get all registered token addresses +- Token bridge configuration for each registered token + +### Token-Specific Configuration (per registered token) +- NEO N3 token hash (corresponding token on Neo blockchain) +- Bridge pause status for the specific token +- Fee amount for token withdrawals +- Minimum and maximum withdrawal amounts +- Maximum number of deposits allowed +- Decimal configuration (decimals on EVM vs NEO, scaling factor) + +### State Information (per registered token) +- Deposit state (EVM to Neo): current nonce and merkle root +- Withdrawal state (Neo to EVM): current nonce and merkle root +- Claimable tokens for specific nonces + +### Usage Notes + +- Set `TOKEN_ADDRESS` environment variable to get detailed information about a specific token +- If no `TOKEN_ADDRESS` is provided, basic bridge information and first registered token info will be shown +- Each token has its own bridge configuration and state tracking +- Claimable tokens are tracked per token address and nonce +- The system supports multiple tokens, each with independent configuration and state diff --git a/src/evm/token-bridge/readOnlyMethods.ts b/src/evm/token-bridge/readOnlyMethods.ts new file mode 100644 index 0000000..d2ab05c --- /dev/null +++ b/src/evm/token-bridge/readOnlyMethods.ts @@ -0,0 +1,134 @@ +import { EvmTokenBridge } from "@bane-labs/bridge-sdk-ts"; +import { ensureEnv } from "../utils"; + +export async function callReadOnlyMethods(tokenBridge: EvmTokenBridge) { + console.log("\n--- Testing EVM Token Bridge Read-Only Methods ---"); + + try { + // Get management contract address + const managementAddress = await tokenBridge.management(); + console.log(`Management Contract Address: ${managementAddress}`); + + // Get bridge pause status + const bridgePaused = await tokenBridge.bridgePaused(); + console.log(`Bridge Paused: ${bridgePaused}`); + + // Get registered tokens list - this returns individual tokens, not an array + // We'll need to handle this differently since registeredTokens(index) returns a single token + let registeredTokens: string[] = []; + try { + // Try to get tokens by index until we hit an error (indicating no more tokens) + let index = 0n; + while (true) { + try { + const token = await tokenBridge.registeredTokens(index); + registeredTokens.push(token); + index++; + } catch { + break; // No more tokens at this index + } + } + } catch (error) { + console.log(`Could not retrieve registered tokens list`); + } + + console.log(`Number of Registered Tokens: ${registeredTokens.length}`); + + if (registeredTokens.length > 0) { + console.log(`Registered Tokens:`); + registeredTokens.forEach((token, index) => { + console.log(` ${index + 1}. ${token}`); + }); + } + + // Get unclaimed rewards + const unclaimedRewards = await tokenBridge.unclaimedRewards(); + console.log(`Unclaimed Rewards: ${unclaimedRewards} wei`); + + // Test with a specific token address if provided + const testTokenAddress = process.env.TOKEN_ADDRESS as `0x${string}`; + if (testTokenAddress) { + console.log(`\n=== Token Bridge Info for ${testTokenAddress} ===`); + + // Check if token is registered using the interface method + const isRegistered = await tokenBridge.isRegisteredToken(testTokenAddress); + console.log(`Is Token Registered: ${isRegistered}`); + + if (isRegistered) { + // Get the token bridge struct for this token + const tokenBridgeStruct = await tokenBridge.tokenBridges(testTokenAddress); + const [paused, depositState, withdrawalState, config] = tokenBridgeStruct; + + console.log(`Token Bridge Paused: ${paused}`); + + // Display token configuration + console.log(`Token Config:`); + console.log(` - NEO N3 Token: ${config.neoN3Token}`); + console.log(` - Fee: ${config.fee}`); + console.log(` - Min Amount: ${config.minAmount}`); + console.log(` - Max Amount: ${config.maxAmount}`); + console.log(` - Max Deposits: ${config.maxDeposits}`); + console.log(` - Decimal Scaling Factor: ${config.decimalScalingFactor}`); + + // Display state information + console.log(`Deposit State - Nonce: ${depositState.nonce}`); + console.log(`Deposit State - Root: ${depositState.root}`); + console.log(`Withdrawal State - Nonce: ${withdrawalState.nonce}`); + console.log(`Withdrawal State - Root: ${withdrawalState.root}`); + + // Test claimable tokens for a specific nonce + const testNonce = process.env.TOKEN_CLAIM_NONCE ? BigInt(process.env.TOKEN_CLAIM_NONCE) : 1n; + try { + const claimable = await tokenBridge.tokenClaimables(testTokenAddress, testNonce); + const [to, amount] = claimable; + console.log(`Claimable for nonce ${testNonce}:`); + console.log(` - To: ${to}`); + console.log(` - Amount: ${amount}`); + } catch (error) { + console.log(`No claimable found for token ${testTokenAddress} at nonce ${testNonce} (this is normal if nothing is claimable)`); + } + } + } else { + console.log(`\n=== Token-Specific Information ===`); + console.log(`Set TOKEN_ADDRESS environment variable to get detailed token information`); + + // If no specific token, show info for first registered token if available + if (registeredTokens.length > 0) { + const firstToken = registeredTokens[0] as `0x${string}`; + console.log(`\nShowing info for first registered token: ${firstToken}`); + + const tokenBridgeStruct = await tokenBridge.tokenBridges(firstToken); + const [paused, , , config] = tokenBridgeStruct; + + console.log(`Token Bridge Paused: ${paused}`); + console.log(`NEO N3 Token: ${config.neoN3Token}`); + console.log(`Fee: ${config.fee}`); + console.log(`Min Amount: ${config.minAmount}`); + console.log(`Max Amount: ${config.maxAmount}`); + } + } + + console.log("\n--- EVM Token Bridge Read-Only Methods Completed Successfully ---"); + } catch (error) { + console.error("Error calling read-only methods:", error); + throw error; + } +} + +async function main() { + ensureEnv(); + + const { createTokenBridgeFromEnvironment } = await import("../utils"); + + try { + const tokenBridge = createTokenBridgeFromEnvironment(); + await callReadOnlyMethods(tokenBridge); + } catch (error) { + console.error("Failed to test EVM Token Bridge read-only methods:", error); + process.exit(1); + } +} + +if (import.meta.url === `file://${process.argv[1]}`) { + main().catch(console.error); +} diff --git a/src/evm/utils.ts b/src/evm/utils.ts new file mode 100644 index 0000000..7d95208 --- /dev/null +++ b/src/evm/utils.ts @@ -0,0 +1,100 @@ +import { + type EvmContractWrapperConfig, + EvmMessageBridge, + EvmExecutionManager, + EvmNativeBridge, + EvmTokenBridge, + EvmBridgeManagement, EvmMessageBridgeBuilder, EvmNativeBridgeBuilder, EvmTokenBridgeBuilder +} from "@bane-labs/bridge-sdk-ts"; +import { createPublicClient, createWalletClient, http, type Address } from 'viem'; +import { privateKeyToAccount } from 'viem/accounts'; +import { mainnet } from 'viem/chains'; +import dotenv from "dotenv"; + +export function ensureEnv() { + dotenv.config(); +} + +export function createEvmContractWrapperConfig(contractAddress: Address): EvmContractWrapperConfig { + const rpcUrl = process.env.EVM_RPC_URL || 'http://localhost:8545'; + const privateKey = process.env.EVM_PRIVATE_KEY; + + const publicClient = createPublicClient({ + chain: mainnet, + transport: http(rpcUrl) + }); + + let walletClient = undefined; + if (privateKey) { + const account = privateKeyToAccount(privateKey as `0x${string}`); + walletClient = createWalletClient({ + account, + chain: mainnet, + transport: http(rpcUrl) + }); + } + + return { + contractAddress, + publicClient, + walletClient + }; +} + +export function createMessageBridgeFromEnvironment(): EvmMessageBridge { + const contractAddress = process.env.EVM_MESSAGE_BRIDGE_CONTRACT_ADDRESS; + if (!contractAddress) { + throw new Error('EVM_MESSAGE_BRIDGE_CONTRACT_ADDRESS environment variable is required'); + } + + const config = createEvmContractWrapperConfig(contractAddress as Address); + return EvmMessageBridgeBuilder.create(config); +} + +export function createExecutionManagerFromEnvironment(): EvmExecutionManager { + const contractAddress = process.env.EVM_EXECUTION_MANAGER_CONTRACT_ADDRESS; + if (!contractAddress) { + throw new Error('EVM_EXECUTION_MANAGER_CONTRACT_ADDRESS environment variable is required'); + } + + const config = createEvmContractWrapperConfig(contractAddress as Address); + return new EvmExecutionManager(config); +} + +export function createNativeBridgeFromEnvironment(): EvmNativeBridge { + const contractAddress = process.env.EVM_NATIVE_BRIDGE_CONTRACT_ADDRESS; + if (!contractAddress) { + throw new Error('EVM_NATIVE_BRIDGE_CONTRACT_ADDRESS environment variable is required'); + } + + const config = createEvmContractWrapperConfig(contractAddress as Address); + return EvmNativeBridgeBuilder.create(config); +} + +export function createTokenBridgeFromEnvironment(): EvmTokenBridge { + const contractAddress = process.env.EVM_TOKEN_BRIDGE_CONTRACT_ADDRESS; + if (!contractAddress) { + throw new Error('EVM_TOKEN_BRIDGE_CONTRACT_ADDRESS environment variable is required'); + } + + const config = createEvmContractWrapperConfig(contractAddress as Address); + return EvmTokenBridgeBuilder.create(config); +} + +export function createBridgeManagementFromEnvironment(): EvmBridgeManagement { + const contractAddress = process.env.EVM_BRIDGE_MANAGEMENT_CONTRACT_ADDRESS; + if (!contractAddress) { + throw new Error('EVM_BRIDGE_MANAGEMENT_CONTRACT_ADDRESS environment variable is required'); + } + + const config = createEvmContractWrapperConfig(contractAddress as Address); + return new EvmBridgeManagement(config); +} + +export function requireEnvVar(name: string): string { + const value = process.env[name]; + if (!value) { + throw new Error(`${name} environment variable is required`); + } + return value; +} From d8a4778bc6e6bd9caf166e304d6a8304c90b1dd0 Mon Sep 17 00:00:00 2001 From: Otniel Nicola Date: Fri, 30 Jan 2026 11:24:37 +0200 Subject: [PATCH 3/8] chore: Update the naming on neo examples --- src/neo/execution-manager/executeMessage.ts | 4 +- src/neo/execution-manager/pauseOperations.ts | 6 +- src/neo/execution-manager/readOnlyMethods.ts | 4 +- src/neo/execution-manager/serializeCall.ts | 4 +- src/neo/message-bridge/executeMessage.ts | 5 +- .../performAllPauseOperations.ts | 6 +- src/neo/message-bridge/readOnlyMethods.ts | 4 +- src/neo/message-bridge/sendMessage.ts | 12 ++-- src/neo/message-bridge/serializeCall.ts | 4 +- src/neo/message-bridge/setExecutionManager.ts | 8 +-- .../native-bridge/nativeBridgeOperations.ts | 22 +++---- src/neo/native-bridge/pauseOperations.ts | 6 +- src/neo/native-bridge/readOnlyMethods.ts | 10 +-- src/neo/token-bridge/readOnlyMethods.ts | 4 +- src/neo/token-bridge/tokenBridgeOperations.ts | 22 +++---- src/neo/utils.ts | 62 +++++++++---------- src/neo/wallet/walletOperations.ts | 14 ++--- 17 files changed, 98 insertions(+), 99 deletions(-) diff --git a/src/neo/execution-manager/executeMessage.ts b/src/neo/execution-manager/executeMessage.ts index 7446064..0711dd9 100644 --- a/src/neo/execution-manager/executeMessage.ts +++ b/src/neo/execution-manager/executeMessage.ts @@ -1,7 +1,7 @@ -import { ExecutionManager } from "@bane-labs/bridge-sdk-ts"; +import { NeoExecutionManager } from "@bane-labs/bridge-sdk-ts"; import { createExecutionManagerFromEnvironment, ensureEnv, waitForStateUpdate } from "../utils"; -async function executeMessage(executionManager: ExecutionManager) { +async function executeMessage(executionManager: NeoExecutionManager) { const nonce = process.env.MESSAGE_NONCE; if (!nonce) { throw new Error('MESSAGE_NONCE environment variable is required for executing messages'); diff --git a/src/neo/execution-manager/pauseOperations.ts b/src/neo/execution-manager/pauseOperations.ts index 57827d9..1b7c75a 100644 --- a/src/neo/execution-manager/pauseOperations.ts +++ b/src/neo/execution-manager/pauseOperations.ts @@ -1,7 +1,7 @@ -import { ExecutionManager, neonAdapter } from "@bane-labs/bridge-sdk-ts"; +import { NeoExecutionManager, neonAdapter } from "@bane-labs/bridge-sdk-ts"; import { createExecutionManagerFromEnvironment, ensureEnv, waitForStateUpdate } from "../utils"; -async function performPauseOperations(executionManager: ExecutionManager) { +async function performPauseOperations(executionManager: NeoExecutionManager) { console.log("\n--- Testing ExecutionManager Pause/Unpause Operations ---"); const config = executionManager.getConfig(); @@ -35,7 +35,7 @@ async function performPauseOperations(executionManager: ExecutionManager) { } } -async function logPauseState(executionManager: ExecutionManager): Promise { +async function logPauseState(executionManager: NeoExecutionManager): Promise { try { const isPaused = await executionManager.isPaused(); console.log(` ExecutionManager Paused: ${isPaused}`); diff --git a/src/neo/execution-manager/readOnlyMethods.ts b/src/neo/execution-manager/readOnlyMethods.ts index 9463bef..202a531 100644 --- a/src/neo/execution-manager/readOnlyMethods.ts +++ b/src/neo/execution-manager/readOnlyMethods.ts @@ -16,10 +16,10 @@ * npm run em:readonly */ -import { ExecutionManager } from "@bane-labs/bridge-sdk-ts"; +import { NeoExecutionManager } from "@bane-labs/bridge-sdk-ts"; import { createExecutionManagerFromEnvironment, ensureEnv } from "../utils"; -export async function callReadOnlyMethods(executionManager: ExecutionManager) { +export async function callReadOnlyMethods(executionManager: NeoExecutionManager) { console.log("\n--- Testing ExecutionManager Read-Only Methods ---"); try { diff --git a/src/neo/execution-manager/serializeCall.ts b/src/neo/execution-manager/serializeCall.ts index 4a3c7d5..dac0ab7 100644 --- a/src/neo/execution-manager/serializeCall.ts +++ b/src/neo/execution-manager/serializeCall.ts @@ -1,7 +1,7 @@ -import { ExecutionManager } from "@bane-labs/bridge-sdk-ts"; +import { NeoExecutionManager } from "@bane-labs/bridge-sdk-ts"; import { createExecutionManagerFromEnvironment, ensureEnv } from "../utils"; -async function serializeCallExamples(executionManager: ExecutionManager) { +async function serializeCallExamples(executionManager: NeoExecutionManager) { console.log("\n--- Testing ExecutionManager Serialization Methods ---"); const target = process.env.SERIALIZE_TARGET || process.env.MESSAGE_BRIDGE_CONTRACT_HASH; diff --git a/src/neo/message-bridge/executeMessage.ts b/src/neo/message-bridge/executeMessage.ts index cbe73eb..ecb9c67 100644 --- a/src/neo/message-bridge/executeMessage.ts +++ b/src/neo/message-bridge/executeMessage.ts @@ -1,7 +1,6 @@ -import { MessageBridge } from "@bane-labs/bridge-sdk-ts"; +import { NeoMessageBridge } from "@bane-labs/bridge-sdk-ts"; import { createMessageBridgeFromEnvironment, ensureEnv, waitForStateUpdate } from "../utils"; - -async function executeMessage(messageBridge: MessageBridge) { +async function executeMessage(messageBridge: NeoMessageBridge) { const nonce = process.env.MESSAGE_NONCE; if (!nonce) { throw new Error('MESSAGE_NONCE environment variable is required for executing messages'); diff --git a/src/neo/message-bridge/performAllPauseOperations.ts b/src/neo/message-bridge/performAllPauseOperations.ts index c6edc8a..7fae39b 100644 --- a/src/neo/message-bridge/performAllPauseOperations.ts +++ b/src/neo/message-bridge/performAllPauseOperations.ts @@ -1,7 +1,7 @@ -import { MessageBridge, neonAdapter } from "@bane-labs/bridge-sdk-ts"; +import { NeoMessageBridge, neonAdapter } from "@bane-labs/bridge-sdk-ts"; import { createMessageBridgeFromEnvironment, ensureEnv, waitForStateUpdate } from "../utils"; -async function performAllPauseOperations(messageBridge: MessageBridge) { +async function performAllPauseOperations(messageBridge: NeoMessageBridge) { console.log("\n--- Testing All Pause/Unpause Operations ---"); // Get block time estimate if available from the rpcClient @@ -72,7 +72,7 @@ async function performAllPauseOperations(messageBridge: MessageBridge) { } } -async function logPauseStates(messageBridge: MessageBridge) { +async function logPauseStates(messageBridge: NeoMessageBridge) { try { const isPaused = await messageBridge.isPaused(); const sendingIsPaused = await messageBridge.sendingIsPaused(); diff --git a/src/neo/message-bridge/readOnlyMethods.ts b/src/neo/message-bridge/readOnlyMethods.ts index e557955..35b9657 100644 --- a/src/neo/message-bridge/readOnlyMethods.ts +++ b/src/neo/message-bridge/readOnlyMethods.ts @@ -1,7 +1,7 @@ -import { MessageBridge } from "@bane-labs/bridge-sdk-ts"; +import { NeoMessageBridge } from "@bane-labs/bridge-sdk-ts"; import { ensureEnv } from "../utils"; -export async function callReadOnlyMethods(messageBridge: MessageBridge) { +export async function callReadOnlyMethods(messageBridge: NeoMessageBridge) { console.log("\n--- Testing Read-Only Methods ---"); try { diff --git a/src/neo/message-bridge/sendMessage.ts b/src/neo/message-bridge/sendMessage.ts index 2093586..c30ec94 100644 --- a/src/neo/message-bridge/sendMessage.ts +++ b/src/neo/message-bridge/sendMessage.ts @@ -1,13 +1,13 @@ import { - GenericError, - MessageBridge, + NeoGenericError, + NeoMessageBridge, type SendExecutableMessageParams, type SendResultMessageParams, type SendStoreOnlyMessageParams } from "@bane-labs/bridge-sdk-ts"; import { createMessageBridgeFromEnvironment, ensureEnv } from "../utils"; -async function sendExecutableMessage(messageBridge: MessageBridge) { +async function sendExecutableMessage(messageBridge: NeoMessageBridge) { const messageData = process.env.MESSAGE_EXECUTABLE_DATA; if (!messageData) { throw new Error('MESSAGE_EXECUTABLE_DATA environment variable is required for executable messages'); @@ -27,7 +27,7 @@ async function sendExecutableMessage(messageBridge: MessageBridge) { console.log('Executable message sent successfully:', result.txHash); } -async function sendResultMessage(messageBridge: MessageBridge) { +async function sendResultMessage(messageBridge: NeoMessageBridge) { const nonce = process.env.MESSAGE_NONCE; if (!nonce) { throw new Error('MESSAGE_NONCE environment variable is required for result messages'); @@ -44,10 +44,10 @@ async function sendResultMessage(messageBridge: MessageBridge) { console.log('Result message sent successfully:', result.txHash); } -async function sendStoreOnlyMessage(messageBridge: MessageBridge) { +async function sendStoreOnlyMessage(messageBridge: NeoMessageBridge) { const messageData = process.env.MESSAGE_STORE_ONLY_DATA; if (!messageData) { - throw new GenericError('MESSAGE_STORE_ONLY_DATA environment variable is required for store-only messages'); + throw new NeoGenericError('MESSAGE_STORE_ONLY_DATA environment variable is required for store-only messages'); } const sendingFee = await messageBridge.sendingFee(); diff --git a/src/neo/message-bridge/serializeCall.ts b/src/neo/message-bridge/serializeCall.ts index c6e9f8a..67c6104 100644 --- a/src/neo/message-bridge/serializeCall.ts +++ b/src/neo/message-bridge/serializeCall.ts @@ -1,7 +1,7 @@ -import { ContractParamType, MessageBridge, neonAdapter } from "@bane-labs/bridge-sdk-ts"; +import { NeoMessageBridge } from "@bane-labs/bridge-sdk-ts"; import { createMessageBridgeFromEnvironment, ensureEnv } from "../utils"; -async function serializeIsPausedCall(messageBridge: MessageBridge) { +async function serializeIsPausedCall(messageBridge: NeoMessageBridge) { const contractHash = process.env.MESSAGE_BRIDGE_CONTRACT_HASH; if (!contractHash) { diff --git a/src/neo/message-bridge/setExecutionManager.ts b/src/neo/message-bridge/setExecutionManager.ts index b673bd5..975fd96 100644 --- a/src/neo/message-bridge/setExecutionManager.ts +++ b/src/neo/message-bridge/setExecutionManager.ts @@ -1,7 +1,7 @@ -import { MessageBridge } from "@bane-labs/bridge-sdk-ts"; +import { NeoMessageBridge } from "@bane-labs/bridge-sdk-ts"; import { createMessageBridgeFromEnvironment, ensureEnv, waitForStateUpdate } from "../utils"; -async function setExecutionManager(messageBridge: MessageBridge) { +async function setExecutionManager(messageBridge: NeoMessageBridge) { const executionManager = process.env.EXECUTION_MANAGER_ADDRESS; if (!executionManager) { @@ -10,7 +10,7 @@ async function setExecutionManager(messageBridge: MessageBridge) { try { const oldExecutionManager = await messageBridge.executionManager(); - console.log('Old execution manager is now set to:', executionManager); + console.log('Old execution manager is now set to:', oldExecutionManager); console.log(`Setting new execution manager: ${executionManager}`); @@ -20,7 +20,7 @@ async function setExecutionManager(messageBridge: MessageBridge) { await waitForStateUpdate(); // Get and log the execution result const newExecutionManager = await messageBridge.executionManager(); - console.log('New execution manager is now set to:', executionManager); + console.log('New execution manager is now set to:', newExecutionManager); } catch (error: any) { console.error('Failed to execute message:', error instanceof Error ? error.message : error); } diff --git a/src/neo/native-bridge/nativeBridgeOperations.ts b/src/neo/native-bridge/nativeBridgeOperations.ts index d94061a..2ede7f8 100644 --- a/src/neo/native-bridge/nativeBridgeOperations.ts +++ b/src/neo/native-bridge/nativeBridgeOperations.ts @@ -1,7 +1,7 @@ import { createNativeBridgeFromEnvironment, ensureEnv } from "../utils"; -import { NativeBridge } from "@bane-labs/bridge-sdk-ts"; +import { NeoNativeBridge } from "@bane-labs/bridge-sdk-ts"; -async function nativeBridgeOperations(nativeBridge: NativeBridge) { +async function nativeBridgeOperations(nativeBridge: NeoNativeBridge) { const operation = process.env.NATIVE_OPERATION; if (!operation) { console.error("Set NATIVE_OPERATION environment variable to specify operation."); @@ -45,7 +45,7 @@ async function nativeBridgeOperations(nativeBridge: NativeBridge) { } } -async function setNativeBridge(nativeBridge: NativeBridge) { +async function setNativeBridge(nativeBridge: NeoNativeBridge) { const tokenForNativeBridge = process.env.NATIVE_TOKEN_ADDRESS; if (!tokenForNativeBridge) { throw new Error('NATIVE_TOKEN_ADDRESS environment variable is required'); @@ -78,7 +78,7 @@ async function setNativeBridge(nativeBridge: NativeBridge) { console.log(`Native bridge set. Transaction: ${result.txHash}`); } -async function depositNative(nativeBridge: NativeBridge) { +async function depositNative(nativeBridge: NeoNativeBridge) { const from = nativeBridge.getConfig().account.scriptHash; const to = process.env.NATIVE_TO_ADDRESS; const amount = process.env.NATIVE_AMOUNT; @@ -102,7 +102,7 @@ async function depositNative(nativeBridge: NativeBridge) { console.log(`Native deposit completed. Transaction: ${result.txHash}`); } -async function claimNative(nativeBridge: NativeBridge) { +async function claimNative(nativeBridge: NeoNativeBridge) { const nonce = process.env.NATIVE_CLAIM_NONCE; if (!nonce) { throw new Error('NATIVE_CLAIM_NONCE environment variable is required'); @@ -115,19 +115,19 @@ async function claimNative(nativeBridge: NativeBridge) { console.log(`Native claim completed. Transaction: ${result.txHash}`); } -async function pauseNativeBridge(nativeBridge: NativeBridge) { +async function pauseNativeBridge(nativeBridge: NeoNativeBridge) { console.log('Pausing native bridge...'); const result = await nativeBridge.pauseNativeBridge(); console.log(`Native bridge paused. Transaction: ${result.txHash}`); } -async function unpauseNativeBridge(nativeBridge: NativeBridge) { +async function unpauseNativeBridge(nativeBridge: NeoNativeBridge) { console.log('Unpausing native bridge...'); const result = await nativeBridge.unpauseNativeBridge(); console.log(`Native bridge unpaused. Transaction: ${result.txHash}`); } -async function setNativeDepositFee(nativeBridge: NativeBridge) { +async function setNativeDepositFee(nativeBridge: NeoNativeBridge) { const newFee = process.env.NEW_NATIVE_DEPOSIT_FEE; if (!newFee) { throw new Error('NEW_NATIVE_DEPOSIT_FEE environment variable is required'); @@ -140,7 +140,7 @@ async function setNativeDepositFee(nativeBridge: NativeBridge) { console.log(`Native deposit fee updated. Transaction: ${result.txHash}`); } -async function setMinNativeDeposit(nativeBridge: NativeBridge) { +async function setMinNativeDeposit(nativeBridge: NeoNativeBridge) { const newMinAmount = process.env.NEW_MIN_NATIVE_DEPOSIT; if (!newMinAmount) { throw new Error('NEW_MIN_NATIVE_DEPOSIT environment variable is required'); @@ -153,7 +153,7 @@ async function setMinNativeDeposit(nativeBridge: NativeBridge) { console.log(`Minimum native deposit updated. Transaction: ${result.txHash}`); } -async function setMaxNativeDeposit(nativeBridge: NativeBridge) { +async function setMaxNativeDeposit(nativeBridge: NeoNativeBridge) { const newMaxAmount = process.env.NEW_MAX_NATIVE_DEPOSIT; if (!newMaxAmount) { throw new Error('NEW_MAX_NATIVE_DEPOSIT environment variable is required'); @@ -166,7 +166,7 @@ async function setMaxNativeDeposit(nativeBridge: NativeBridge) { console.log(`Maximum native deposit updated. Transaction: ${result.txHash}`); } -async function setMaxTotalDepositedNative(nativeBridge: NativeBridge) { +async function setMaxTotalDepositedNative(nativeBridge: NeoNativeBridge) { const newMaxTotalDeposited = process.env.NEW_MAX_TOTAL_DEPOSITED_NATIVE; if (!newMaxTotalDeposited) { throw new Error('NEW_MAX_TOTAL_DEPOSITED_NATIVE environment variable is required'); diff --git a/src/neo/native-bridge/pauseOperations.ts b/src/neo/native-bridge/pauseOperations.ts index 98f3bb4..98e2608 100644 --- a/src/neo/native-bridge/pauseOperations.ts +++ b/src/neo/native-bridge/pauseOperations.ts @@ -1,7 +1,7 @@ -import { NativeBridge, neonAdapter } from "@bane-labs/bridge-sdk-ts"; +import { NeoNativeBridge, neonAdapter } from "@bane-labs/bridge-sdk-ts"; import { createNativeBridgeFromEnvironment, ensureEnv, waitForStateUpdate } from "../utils"; -async function pauseOperations(nativeBridge: NativeBridge) { +async function pauseOperations(nativeBridge: NeoNativeBridge) { console.log("\n--- Testing Native Bridge Pause/Unpause Operations ---"); const config = nativeBridge.getConfig(); @@ -62,7 +62,7 @@ async function pauseOperations(nativeBridge: NativeBridge) { } } -async function logPauseStates(nativeBridge: NativeBridge) { +async function logPauseStates(nativeBridge: NeoNativeBridge) { try { const bridgeIsPaused = await nativeBridge.isPaused(); console.log(` Bridge Paused: ${bridgeIsPaused}`); diff --git a/src/neo/native-bridge/readOnlyMethods.ts b/src/neo/native-bridge/readOnlyMethods.ts index 1103ca6..54b82b5 100644 --- a/src/neo/native-bridge/readOnlyMethods.ts +++ b/src/neo/native-bridge/readOnlyMethods.ts @@ -13,7 +13,7 @@ * npm run nb:readonly */ import { createNativeBridgeFromEnvironment, ensureEnv } from "../utils"; -import { NativeBridge, getAllBalances, neonAdapter, type AssetBalance } from "@bane-labs/bridge-sdk-ts"; +import { NeoNativeBridge, getAllBalances, neonAdapter, type NeoAssetBalance } from "@bane-labs/bridge-sdk-ts"; // Known token contract hashes const TOKEN_HASHES = neonAdapter.constants.NATIVE_CONTRACT_HASH; @@ -30,7 +30,7 @@ function getTokenName(tokenHash: string): string { } } -function displayBalances(balances: AssetBalance[]): void { +function displayBalances(balances: NeoAssetBalance[]): void { balances.forEach((balance) => { if (balance && balance.assethash && balance.amount !== undefined) { const tokenName = getTokenName(balance.assethash); @@ -45,10 +45,10 @@ async function checkBridgeBalances(bridgeAddress: string, rpcUrl: string): Promi console.log(`Bridge Address: ${bridgeAddress}`); const rpcClient = neonAdapter.create.rpcClient(rpcUrl); - const balances = await getAllBalances(rpcClient, bridgeAddress) as AssetBalance[]; + const balances = await getAllBalances(rpcClient, bridgeAddress) as NeoAssetBalance[]; if (balances && Array.isArray(balances) && balances.length > 0) { - const validBalances = balances.filter((balance): balance is AssetBalance => + const validBalances = balances.filter((balance): balance is NeoAssetBalance => balance !== null && balance !== undefined && 'assethash' in balance && @@ -72,7 +72,7 @@ async function checkBridgeBalances(bridgeAddress: string, rpcUrl: string): Promi } } -export async function callReadOnlyMethods(nativeBridge: NativeBridge) { +export async function callReadOnlyMethods(nativeBridge: NeoNativeBridge) { console.log("\n--- Testing Native Bridge Read-Only Methods ---"); try { diff --git a/src/neo/token-bridge/readOnlyMethods.ts b/src/neo/token-bridge/readOnlyMethods.ts index 77fa7e8..83bfe73 100644 --- a/src/neo/token-bridge/readOnlyMethods.ts +++ b/src/neo/token-bridge/readOnlyMethods.ts @@ -13,9 +13,9 @@ * npm run tb:readonly */ import { createTokenBridgeFromEnvironment, ensureEnv } from "../utils"; -import { TokenBridge } from "@bane-labs/bridge-sdk-ts"; +import { NeoTokenBridge } from "@bane-labs/bridge-sdk-ts"; -export async function callReadOnlyMethods(tokenBridge: TokenBridge) { +export async function callReadOnlyMethods(tokenBridge: NeoTokenBridge) { console.log("\n--- Testing Token Bridge Read-Only Methods ---"); try { diff --git a/src/neo/token-bridge/tokenBridgeOperations.ts b/src/neo/token-bridge/tokenBridgeOperations.ts index 21d4985..3e9d7af 100644 --- a/src/neo/token-bridge/tokenBridgeOperations.ts +++ b/src/neo/token-bridge/tokenBridgeOperations.ts @@ -1,7 +1,7 @@ import { createTokenBridgeFromEnvironment, ensureEnv } from "../utils"; -import { TokenBridge } from "@bane-labs/bridge-sdk-ts"; +import { NeoTokenBridge } from "@bane-labs/bridge-sdk-ts"; -async function tokenBridgeOperations(tokenBridge: TokenBridge) { +async function tokenBridgeOperations(tokenBridge: NeoTokenBridge) { console.log("\n--- Testing Token Bridge Operations ---"); const operation = process.env.TOKEN_OPERATION; @@ -47,7 +47,7 @@ async function tokenBridgeOperations(tokenBridge: TokenBridge) { } } -async function registerToken(tokenBridge: TokenBridge) { +async function registerToken(tokenBridge: NeoTokenBridge) { const token = process.env.TOKEN_ADDRESS; if (!token) { throw new Error('TOKEN_ADDRESS environment variable is required'); @@ -79,7 +79,7 @@ async function registerToken(tokenBridge: TokenBridge) { console.log(`Token registered. Transaction: ${result.txHash}`); } -async function depositToken(tokenBridge: TokenBridge) { +async function depositToken(tokenBridge: NeoTokenBridge) { const token = process.env.TOKEN_ADDRESS; const from = tokenBridge.getConfig().account.scriptHash; const to = process.env.TOKEN_TO_ADDRESS; @@ -105,7 +105,7 @@ async function depositToken(tokenBridge: TokenBridge) { console.log(`Token deposit completed. Transaction: ${result.txHash}`); } -async function claimToken(tokenBridge: TokenBridge) { +async function claimToken(tokenBridge: NeoTokenBridge) { const token = process.env.TOKEN_ADDRESS; const nonce = process.env.TOKEN_CLAIM_NONCE; @@ -120,7 +120,7 @@ async function claimToken(tokenBridge: TokenBridge) { console.log(`Token claim completed. Transaction: ${result.txHash}`); } -async function pauseTokenBridge(tokenBridge: TokenBridge) { +async function pauseTokenBridge(tokenBridge: NeoTokenBridge) { const neoN3Token = process.env.TOKEN_ADDRESS; if (!neoN3Token) { throw new Error('TOKEN_ADDRESS environment variable is required'); @@ -131,7 +131,7 @@ async function pauseTokenBridge(tokenBridge: TokenBridge) { console.log(`Token bridge paused. Transaction: ${result.txHash}`); } -async function unpauseTokenBridge(tokenBridge: TokenBridge) { +async function unpauseTokenBridge(tokenBridge: NeoTokenBridge) { const neoN3Token = process.env.TOKEN_ADDRESS; if (!neoN3Token) { throw new Error('TOKEN_ADDRESS environment variable is required'); @@ -142,7 +142,7 @@ async function unpauseTokenBridge(tokenBridge: TokenBridge) { console.log(`Token bridge unpaused. Transaction: ${result.txHash}`); } -async function setTokenDepositFee(tokenBridge: TokenBridge) { +async function setTokenDepositFee(tokenBridge: NeoTokenBridge) { const token = process.env.TOKEN_ADDRESS; const newFee = process.env.NEW_TOKEN_DEPOSIT_FEE; @@ -163,7 +163,7 @@ async function setTokenDepositFee(tokenBridge: TokenBridge) { console.log(`Token deposit fee updated. Transaction: ${result.txHash}`); } -async function setMinTokenDeposit(tokenBridge: TokenBridge) { +async function setMinTokenDeposit(tokenBridge: NeoTokenBridge) { const token = process.env.TOKEN_ADDRESS; const newMinDeposit = process.env.NEW_MIN_TOKEN_DEPOSIT; @@ -181,7 +181,7 @@ async function setMinTokenDeposit(tokenBridge: TokenBridge) { console.log(`Minimum token deposit updated. Transaction: ${result.txHash}`); } -async function setMaxTokenDeposit(tokenBridge: TokenBridge) { +async function setMaxTokenDeposit(tokenBridge: NeoTokenBridge) { const token = process.env.TOKEN_ADDRESS; const newMaxDeposit = process.env.NEW_MAX_TOKEN_DEPOSIT; @@ -199,7 +199,7 @@ async function setMaxTokenDeposit(tokenBridge: TokenBridge) { console.log(`Maximum token deposit updated. Transaction: ${result.txHash}`); } -async function setMaxTokenWithdrawals(tokenBridge: TokenBridge) { +async function setMaxTokenWithdrawals(tokenBridge: NeoTokenBridge) { const token = process.env.TOKEN_ADDRESS; const newMaxWithdrawals = process.env.NEW_MAX_TOKEN_WITHDRAWALS; diff --git a/src/neo/utils.ts b/src/neo/utils.ts index bc5b944..88aef0e 100644 --- a/src/neo/utils.ts +++ b/src/neo/utils.ts @@ -1,14 +1,14 @@ import { type Account, - type ContractWrapperConfig, + type NeoContractWrapperConfig, createAccountFromWalletFile, createDecryptedAccountFromWalletFile, - GenericError, - BridgeManagement, - MessageBridge, - NativeBridge, - TokenBridge, - ExecutionManager + NeoGenericError, + NeoBridgeManagement, + NeoMessageBridge, + NeoNativeBridge, + NeoTokenBridge, + NeoExecutionManager } from "@bane-labs/bridge-sdk-ts"; import dotenv from "dotenv"; @@ -17,78 +17,78 @@ export function ensureEnv() { dotenv.config(); } -export async function createMessageBridgeFromEnvironment(): Promise { +export async function createMessageBridgeFromEnvironment(): Promise { const contractHash = process.env.MESSAGE_BRIDGE_CONTRACT_HASH; if (!contractHash) { - throw new GenericError('MESSAGE_BRIDGE_CONTRACT_HASH environment variable is required', 'MISSING_CONTRACT_HASH'); + throw new NeoGenericError('MESSAGE_BRIDGE_CONTRACT_HASH environment variable is required', 'MISSING_CONTRACT_HASH'); } const config = await createContractWrapperConfigFromEnv(contractHash); - return new MessageBridge(config); + return new NeoMessageBridge(config); } -export async function createExecutionManagerFromEnvironment(): Promise { +export async function createExecutionManagerFromEnvironment(): Promise { const contractHash = process.env.EXECUTION_MANAGER_CONTRACT_HASH; if (!contractHash) { - throw new GenericError('EXECUTION_MANAGER_CONTRACT_HASH environment variable is required', 'MISSING_CONTRACT_HASH'); + throw new NeoGenericError('EXECUTION_MANAGER_CONTRACT_HASH environment variable is required', 'MISSING_CONTRACT_HASH'); } const config = await createContractWrapperConfigFromEnv(contractHash); - return new ExecutionManager(config); + return new NeoExecutionManager(config); } -export async function createNativeBridgeFromEnvironment(): Promise { +export async function createNativeBridgeFromEnvironment(): Promise { const contractHash = process.env.NATIVE_BRIDGE_CONTRACT_HASH; if (!contractHash) { - throw new GenericError('NATIVE_BRIDGE_CONTRACT_HASH environment variable is required', 'MISSING_CONTRACT_HASH'); + throw new NeoGenericError('NATIVE_BRIDGE_CONTRACT_HASH environment variable is required', 'MISSING_CONTRACT_HASH'); } const config = await createContractWrapperConfigFromEnv(contractHash); - return new NativeBridge(config); + return new NeoNativeBridge(config); } -export async function createTokenBridgeFromEnvironment(): Promise { +export async function createTokenBridgeFromEnvironment(): Promise { const contractHash = process.env.TOKEN_BRIDGE_CONTRACT_HASH; if (!contractHash) { - throw new GenericError('TOKEN_BRIDGE_CONTRACT_HASH environment variable is required', 'MISSING_CONTRACT_HASH'); + throw new NeoGenericError('TOKEN_BRIDGE_CONTRACT_HASH environment variable is required', 'MISSING_CONTRACT_HASH'); } const config = await createContractWrapperConfigFromEnv(contractHash); - return new TokenBridge(config); + return new NeoTokenBridge(config); } // Legacy function for backward compatibility -export async function createNativeTokenBridgeFromEnvironment(): Promise { +export async function createNativeTokenBridgeFromEnvironment(): Promise { console.warn('createNativeTokenBridgeFromEnvironment is deprecated. Use createNativeBridgeFromEnvironment instead.'); return createNativeBridgeFromEnvironment(); } -export async function createManagementFromEnvironment(): Promise { +export async function createManagementFromEnvironment(): Promise { const contractHash = process.env.BRIDGE_MANAGEMENT_CONTRACT_HASH; const rpcUrl = process.env.NEO_NODE_URL; const walletPath = process.env.WALLET_PATH; const walletPassword = process.env.WALLET_PASSWORD || ''; if (!contractHash) { - throw new GenericError('BRIDGE_MANAGEMENT_CONTRACT_HASH environment variable is required', 'MISSING_CONTRACT_HASH'); + throw new NeoGenericError('BRIDGE_MANAGEMENT_CONTRACT_HASH environment variable is required', 'MISSING_CONTRACT_HASH'); } if (!rpcUrl) { - throw new GenericError('NEO_NODE_URL environment variable is required', 'MISSING_RPC_URL'); + throw new NeoGenericError('NEO_NODE_URL environment variable is required', 'MISSING_RPC_URL'); } if (!walletPath) { - throw new GenericError('WALLET_PATH environment variable is required', 'MISSING_WALLET_PATH'); + throw new NeoGenericError('WALLET_PATH environment variable is required', 'MISSING_WALLET_PATH'); } const account = await createDecryptedAccountFromWalletFile(walletPath, walletPassword); if (!account) { - throw new GenericError('Failed to load account from wallet file.', 'ACCOUNT_LOAD_FAILED'); + throw new NeoGenericError('Failed to load account from wallet file.', 'ACCOUNT_LOAD_FAILED'); } const config = {contractHash, rpcUrl, account}; - return new BridgeManagement(config); + return new NeoBridgeManagement(config); } export function waitForStateUpdate(waitMs: number = 1000): Promise { @@ -99,7 +99,7 @@ export function waitForStateUpdate(waitMs: number = 1000): Promise { async function createContractWrapperConfigFromEnv(contractHash: string) { const walletPath = process.env.WALLET_PATH; if (!walletPath) { - throw new GenericError('WALLET_PATH environment variable is required', 'MISSING_WALLET_PATH'); + throw new NeoGenericError('WALLET_PATH environment variable is required', 'MISSING_WALLET_PATH'); } const walletPassword = process.env.WALLET_PASSWORD || ''; @@ -112,7 +112,7 @@ async function createContractWrapperConfigFromEnv(contractHash: string) { account = createAccountFromWalletFile(walletPath); if (account && (account.tryGet("encrypted") || account.tryGet("WIF"))) { - throw new GenericError( + throw new NeoGenericError( 'Wallet contains encrypted private key but no WALLET_PASSWORD environment variable provided. Please set WALLET_PASSWORD to decrypt the wallet.', 'ENCRYPTED_WALLET_NO_PASSWORD' ); @@ -120,14 +120,14 @@ async function createContractWrapperConfigFromEnv(contractHash: string) { } if (!account) { - throw new GenericError('Failed to load account from wallet file', 'ACCOUNT_LOAD_FAILED'); + throw new NeoGenericError('Failed to load account from wallet file', 'ACCOUNT_LOAD_FAILED'); } if (!rpcUrl) { - throw new GenericError('NEO_NODE_URL environment variable is required', 'MISSING_RPC_URL'); + throw new NeoGenericError('NEO_NODE_URL environment variable is required', 'MISSING_RPC_URL'); } - const config: ContractWrapperConfig = { + const config: NeoContractWrapperConfig = { contractHash, rpcUrl, account diff --git a/src/neo/wallet/walletOperations.ts b/src/neo/wallet/walletOperations.ts index b659627..1b2b76c 100644 --- a/src/neo/wallet/walletOperations.ts +++ b/src/neo/wallet/walletOperations.ts @@ -1,6 +1,6 @@ import { - type AssetBalance, - type BalanceResponse, + type NeoAssetBalance, + type NeoBalanceResponse, createAccountFromWalletFile, createDecryptedAccountFromWalletFile, createWalletFromFile, @@ -12,7 +12,7 @@ import { ensureEnv } from "../utils"; // Type definitions for better type safety interface BalanceCache { [address: string]: { - balances: AssetBalance[]; + balances: NeoAssetBalance[]; timestamp: number; }; } @@ -49,7 +49,7 @@ function isCacheValid(address: string): boolean { return cached && (Date.now() - cached.timestamp) < CACHE_DURATION; } -export function displayBalances(balances: AssetBalance[]): void { +export function displayBalances(balances: NeoAssetBalance[]): void { balances.forEach((balance) => { if (balance && balance.assethash && balance.amount !== undefined) { const tokenName = getTokenName(balance.assethash); @@ -86,13 +86,13 @@ async function checkAccountBalances(accountAddress: string, rpcUrl: string, acco } const rpcClient = neonAdapter.create.rpcClient(rpcUrl); - const balances = await getAllBalances(rpcClient, accountAddress) as AssetBalance[]; + const balances = await getAllBalances(rpcClient, accountAddress) as NeoAssetBalance[]; console.log("Account Balances:"); if (balances && Array.isArray(balances) && balances.length > 0) { // Validate balance structure for type safety - const validBalances = balances.filter((balance): balance is AssetBalance => + const validBalances = balances.filter((balance): balance is NeoAssetBalance => balance !== null && balance !== undefined && 'assethash' in balance && @@ -122,7 +122,7 @@ async function checkAccountBalances(accountAddress: string, rpcUrl: string, acco } // Export types for external use -export type { AssetBalance, BalanceResponse, BalanceCache, AccountInfo }; +export type { NeoAssetBalance, NeoBalanceResponse, BalanceCache, AccountInfo }; export async function testWalletOperations(): Promise { const walletPath = process.env.WALLET_PATH; From eb59d281a5b1d604075bca10a0cfe57fdde7b110 Mon Sep 17 00:00:00 2001 From: Otniel Nicola Date: Fri, 30 Jan 2026 12:45:23 +0200 Subject: [PATCH 4/8] feat: Add write methods --- README.md | 61 ++++-- package-lock.json | 2 +- package.json | 34 ++- src/evm/bridge-management/README.md | 7 +- .../bridge-management/ownerRelayerGovernor.ts | 62 ++++++ .../bridge-management/validatorManagement.ts | 62 ++++++ src/evm/message-bridge/README.md | 6 + .../message-bridge/encodeExecutableMessage.ts | 200 ++++++++++++++++++ src/evm/native-bridge/README.md | 19 +- .../native-bridge/nativeBridgeOperations.ts | 165 +++++++++++++++ src/evm/native-bridge/pauseOperations.ts | 94 ++++++++ src/evm/token-bridge/README.md | 13 ++ src/evm/token-bridge/tokenBridgeOperations.ts | 188 ++++++++++++++++ src/evm/utils.ts | 13 +- src/neo/execution-manager/README.md | 9 +- src/neo/management/README.md | 20 +- src/neo/message-bridge/README.md | 17 +- src/neo/message-bridge/sendMessage.ts | 12 +- src/neo/native-bridge/README.md | 24 +-- src/neo/token-bridge/README.md | 22 +- src/neo/wallet/README.md | 2 +- tsconfig.json | 2 +- 22 files changed, 948 insertions(+), 86 deletions(-) create mode 100644 src/evm/bridge-management/ownerRelayerGovernor.ts create mode 100644 src/evm/bridge-management/validatorManagement.ts create mode 100644 src/evm/message-bridge/encodeExecutableMessage.ts create mode 100644 src/evm/native-bridge/nativeBridgeOperations.ts create mode 100644 src/evm/native-bridge/pauseOperations.ts create mode 100644 src/evm/token-bridge/tokenBridgeOperations.ts diff --git a/README.md b/README.md index 5f19fdd..cff36cd 100644 --- a/README.md +++ b/README.md @@ -1,13 +1,13 @@ # TypeScript Examples for Bridge Contracts -This directory contains TypeScript scripts demonstrating how to interact with various bridge contracts on Neo using the `bridge-sdk-ts` library. +This directory contains TypeScript scripts demonstrating how to interact with various bridge contracts on both Neo and EVM chains using the `@bane-labs/bridge-sdk-ts` library. ## Prerequisites - Node.js v18 or newer - npm -- Access to a running Neo node (local or remote) -- A valid Neo wallet file (JSON format) -- Contract hashes for the deployed bridge contracts +- Access to running nodes (Neo and/or EVM compatible) +- Valid wallet configurations for target chains +- Contract addresses/hashes for deployed bridge contracts ## Setup 1. Install dependencies: @@ -18,31 +18,56 @@ This directory contains TypeScript scripts demonstrating how to interact with va ```sh cp env-template .env ``` - Edit `.env` and set values for: - - Contract hashes for deployed bridge contracts (e.g., `MESSAGE_BRIDGE_CONTRACT_HASH`, `NATIVE_BRIDGE_CONTRACT_HASH`, etc.) - - `NEO_NODE_URL` (RPC URL) - - `WALLET_PATH` (path to your Neo wallet JSON) - - `WALLET_PASSWORD` (if your wallet is encrypted) - - Other variables as needed for specific scripts + Edit `.env` and configure values for your target chain(s). See [Environment Variables](#environment-variables) section below. ## Usage -Scripts are organized by bridge component. See the subdirectories below for specific usage instructions and npm scripts. +Scripts are organized by blockchain platform and bridge component. All scripts can be run using npm scripts with the following naming conventions: +- **Neo**: `npm run neo::` +- **EVM**: `npm run evm::` + +See the platform-specific sections below and individual README files for detailed instructions. ## Environment Variables -See `env-template` for all required and optional variables. Key variables include: -- `NEO_NODE_URL` -- `WALLET_PATH` -- `WALLET_PASSWORD` +See `env-template` for all required and optional variables. + +### Neo Chain Variables +- `NEO_NODE_URL` - RPC URL of the Neo node +- `WALLET_PATH` - Path to your Neo wallet JSON file +- `WALLET_PASSWORD` - Password for the wallet (if encrypted) - Contract-specific hashes (e.g., `MESSAGE_BRIDGE_CONTRACT_HASH`, `NATIVE_BRIDGE_CONTRACT_HASH`) -- Operation-specific variables (see subdirectory READMEs for details) -## Bridge Components +### EVM Chain Variables +- `EVM_RPC_URL` - RPC URL of the EVM node (defaults to http://localhost:8545) +- `EVM_PRIVATE_KEY` - Private key for the wallet (required for write operations) +- Contract-specific addresses (e.g., `EVM_MESSAGE_BRIDGE_CONTRACT_ADDRESS`, `EVM_NATIVE_BRIDGE_CONTRACT_ADDRESS`) + +### Operation-specific Variables +Each operation may require additional variables. See subdirectory READMEs for details. + +## Neo Bridge Components - **Native Bridge**: Handles native token (GAS/NEO) bridging. See [src/neo/native-bridge/README.md](src/neo/native-bridge/README.md) - **Token Bridge**: Handles NEP-17 token bridging. See [src/neo/token-bridge/README.md](src/neo/token-bridge/README.md) - **Message Bridge**: Handles cross-chain message bridging. See [src/neo/message-bridge/README.md](src/neo/message-bridge/README.md) - **Management**: Handles ownership, relayer, governor, security guard, and validator management. See [src/neo/management/README.md](src/neo/management/README.md) - **Execution Manager**: Handles message execution and bridge management. See [src/neo/execution-manager/README.md](src/neo/execution-manager/README.md) -- **Wallet Operations**: Examples for wallet interactions. See [src/neo/wallet/walletOperations.ts](src/neo/wallet/walletOperations.ts) +- **Wallet Operations**: Examples for wallet interactions. See [src/neo/wallet/README.md](src/neo/wallet/README.md) + +## EVM Bridge Components +- **Message Bridge**: Handles cross-chain message bridging operations between EVM and Neo. See [src/evm/message-bridge/README.md](src/evm/message-bridge/README.md) +- **Execution Manager**: Handles message execution and management. See [src/evm/execution-manager/README.md](src/evm/execution-manager/README.md) +- **Native Bridge**: Handles native token bridging operations. See [src/evm/native-bridge/README.md](src/evm/native-bridge/README.md) +- **Token Bridge**: Handles ERC-20 token bridging operations. See [src/evm/token-bridge/README.md](src/evm/token-bridge/README.md) +- **Bridge Management**: Handles governance and validator management. See [src/evm/bridge-management/README.md](src/evm/bridge-management/README.md) + +For a comprehensive overview of EVM examples, see [src/evm/README.md](src/evm/README.md). + +## Notes +- Ensure your `.env` file does **not** use quotes or semicolons around values. +- Wallet file paths should be relative to this directory or absolute. +- Scripts are modular; you can add or modify npm scripts in `package.json` as needed. +- All EVM examples now include complete management, execution, message bridge, native bridge, and token bridge operations. + +For more details, see the comments in each script file. ## Notes - Ensure your `.env` file does **not** use quotes or semicolons around values. diff --git a/package-lock.json b/package-lock.json index eff4e92..3d0c04a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -27,7 +27,7 @@ "node_modules/@bane-labs/bridge-sdk-ts": { "version": "1.0.0-beta.7", "resolved": "file:../../../bridge-sdk-ts/bane-labs-bridge-sdk-ts-1.0.0-beta.7.tgz", - "integrity": "sha512-NCgKSqYcQ3FseqJ0PL9wuzjR5YEkPkyjya0nmSsiu/+dAAavM22dVH1/vToqllRO8SMKqe2aAZgB6NsL6PFzvQ==", + "integrity": "sha512-w0YM24Ct+q6E+lc4HGSAobpYZDV3xqfKRC1EJdqif23FnSQMIqZq/kHR7UVWAJVWcHA+hLD/9S2LV9n9KW6t1g==", "license": "Apache-2.0", "dependencies": { "@cityofzion/neon-js": "5.8.0", diff --git a/package.json b/package.json index 7bb0447..8e59f0e 100644 --- a/package.json +++ b/package.json @@ -8,7 +8,7 @@ "scripts": { "neo:amb:serialize": "tsx src/neo/message-bridge/serializeCall.ts", "neo:amb:execute": "tsx src/neo/message-bridge/executeMessage.ts", - "neo:amb:send-excutable": "MESSAGE_BRIDGE_OPERATION=send-executable tsx src/neo/message-bridge/sendMessage.ts", + "neo:amb:send-executable": "MESSAGE_BRIDGE_OPERATION=send-executable tsx src/neo/message-bridge/sendMessage.ts", "neo:amb:send-result": "MESSAGE_BRIDGE_OPERATION=send-result tsx src/neo/message-bridge/sendMessage.ts", "neo:amb:send-store-only": "MESSAGE_BRIDGE_OPERATION=send-store-only tsx src/neo/message-bridge/sendMessage.ts", "neo:amb:set-executor": "tsx src/neo/message-bridge/setExecutionManager.ts", @@ -59,12 +59,42 @@ "evm:amb:send-result": "MESSAGE_BRIDGE_OPERATION=send-result tsx src/evm/message-bridge/sendMessage.ts", "evm:amb:send-store-only": "MESSAGE_BRIDGE_OPERATION=send-store-only tsx src/evm/message-bridge/sendMessage.ts", "evm:amb:set-executor": "tsx src/evm/message-bridge/setExecutionManager.ts", + "evm:amb:encode-message": "tsx src/evm/message-bridge/encodeExecutableMessage.ts", "evm:em:execute": "tsx src/evm/execution-manager/executeMessage.ts", "evm:em:readonly": "tsx src/evm/execution-manager/readOnlyMethods.ts", "evm:nb:readonly": "tsx src/evm/native-bridge/readOnlyMethods.ts", + "evm:nb:operations": "tsx src/evm/native-bridge/nativeBridgeOperations.ts", + "evm:nb:pause": "tsx src/evm/native-bridge/pauseOperations.ts", + "evm:nb:set": "NATIVE_OPERATION=set tsx src/evm/native-bridge/nativeBridgeOperations.ts", + "evm:nb:deposit": "NATIVE_OPERATION=deposit tsx src/evm/native-bridge/nativeBridgeOperations.ts", + "evm:nb:claim": "NATIVE_OPERATION=claim tsx src/evm/native-bridge/nativeBridgeOperations.ts", + "evm:nb:pause-bridge": "NATIVE_OPERATION=pause-bridge tsx src/evm/native-bridge/nativeBridgeOperations.ts", + "evm:nb:unpause-bridge": "NATIVE_OPERATION=unpause-bridge tsx src/evm/native-bridge/nativeBridgeOperations.ts", + "evm:nb:set-fee": "NATIVE_OPERATION=set-fee tsx src/evm/native-bridge/nativeBridgeOperations.ts", + "evm:nb:set-min": "NATIVE_OPERATION=set-min tsx src/evm/native-bridge/nativeBridgeOperations.ts", + "evm:nb:set-max": "NATIVE_OPERATION=set-max tsx src/evm/native-bridge/nativeBridgeOperations.ts", + "evm:nb:set-total": "NATIVE_OPERATION=set-total tsx src/evm/native-bridge/nativeBridgeOperations.ts", "evm:tb:readonly": "tsx src/evm/token-bridge/readOnlyMethods.ts", + "evm:tb:operations": "tsx src/evm/token-bridge/tokenBridgeOperations.ts", + "evm:tb:register": "TOKEN_OPERATION=register tsx src/evm/token-bridge/tokenBridgeOperations.ts", + "evm:tb:deposit": "TOKEN_OPERATION=deposit tsx src/evm/token-bridge/tokenBridgeOperations.ts", + "evm:tb:claim": "TOKEN_OPERATION=claim tsx src/evm/token-bridge/tokenBridgeOperations.ts", + "evm:tb:pause": "TOKEN_OPERATION=pause tsx src/evm/token-bridge/tokenBridgeOperations.ts", + "evm:tb:unpause": "TOKEN_OPERATION=unpause tsx src/evm/token-bridge/tokenBridgeOperations.ts", + "evm:tb:set-fee": "TOKEN_OPERATION=set-fee tsx src/evm/token-bridge/tokenBridgeOperations.ts", + "evm:tb:set-min": "TOKEN_OPERATION=set-min tsx src/evm/token-bridge/tokenBridgeOperations.ts", + "evm:tb:set-max": "TOKEN_OPERATION=set-max tsx src/evm/token-bridge/tokenBridgeOperations.ts", + "evm:tb:set-withdrawals": "TOKEN_OPERATION=set-withdrawals tsx src/evm/token-bridge/tokenBridgeOperations.ts", "evm:mgmt:readonly": "tsx src/evm/bridge-management/readOnlyMethods.ts", - "evm:wallet": "tsx src/evm/wallet/walletOperations.ts" + "evm:mgmt:validator-add": "VALIDATOR_ACTION=add tsx src/evm/bridge-management/validatorManagement.ts", + "evm:mgmt:validator-remove": "VALIDATOR_ACTION=remove tsx src/evm/bridge-management/validatorManagement.ts", + "evm:mgmt:validator-replace": "VALIDATOR_ACTION=replace tsx src/evm/bridge-management/validatorManagement.ts", + "evm:mgmt:validator-threshold": "VALIDATOR_ACTION=set-threshold tsx src/evm/bridge-management/validatorManagement.ts", + "evm:mgmt:transfer-ownership": "MANAGEMENT_ACTION=transfer-ownership tsx src/evm/bridge-management/ownerRelayerGovernor.ts", + "evm:mgmt:accept-ownership": "MANAGEMENT_ACTION=accept-ownership tsx src/evm/bridge-management/ownerRelayerGovernor.ts", + "evm:mgmt:set-relayer": "MANAGEMENT_ACTION=set-relayer tsx src/evm/bridge-management/ownerRelayerGovernor.ts", + "evm:mgmt:set-governor": "MANAGEMENT_ACTION=set-governor tsx src/evm/bridge-management/ownerRelayerGovernor.ts", + "evm:mgmt:set-security-guard": "MANAGEMENT_ACTION=set-security-guard tsx src/evm/bridge-management/ownerRelayerGovernor.ts" }, "dependencies": { "@bane-labs/bridge-sdk-ts": "file:../../../bridge-sdk-ts/bane-labs-bridge-sdk-ts-1.0.0-beta.7.tgz", diff --git a/src/evm/bridge-management/README.md b/src/evm/bridge-management/README.md index 1450ff0..13ca104 100644 --- a/src/evm/bridge-management/README.md +++ b/src/evm/bridge-management/README.md @@ -13,12 +13,13 @@ This directory contains examples for interacting with the EVM Bridge Management ### Bridge Management Operations - `npm run evm:mgmt:readonly` - Read all bridge management state information - `npm run evm:mgmt:validator-add` - Add a new validator -- `npm run evm:mgmt:validator-remove` - Remove a validator +- `npm run evm:mgmt:validator-remove` - Remove a validator - `npm run evm:mgmt:validator-replace` - Replace an existing validator - `npm run evm:mgmt:validator-threshold` - Set validator threshold - `npm run evm:mgmt:set-owner` - Set contract owner - `npm run evm:mgmt:set-relayer` - Set relayer address - `npm run evm:mgmt:set-governor` - Set governor address +- `npm run evm:mgmt:set-security` - Set security guard address ## Required Environment Variables @@ -27,5 +28,7 @@ This directory contains examples for interacting with the EVM Bridge Management - `EVM_PRIVATE_KEY` - Private key for the wallet (required for write operations) ### Operation-specific Variables -- For validator operations: `VALIDATOR_ADDRESS`, `NEW_VALIDATOR_ADDRESS`, `VALIDATOR_THRESHOLD` +- For `ownerRelayerGovernor.ts`: `MANAGEMENT_ACTION` (set-owner, set-relayer, set-governor, set-security-guard), corresponding `NEW_OWNER`, `NEW_RELAYER`, `NEW_GOVERNOR`, `NEW_SECURITY_GUARD` +- For `validatorManagement.ts`: `VALIDATOR_ACTION` (add, remove, replace, set-threshold), `VALIDATOR_ADDRESS`, `OLD_VALIDATOR_ADDRESS`, `NEW_VALIDATOR_ADDRESS`, `VALIDATOR_THRESHOLD` +- For `readOnlyMethods.ts`: Optional `VALIDATOR_ADDRESS` to check if a specific address is a validator - For role operations: `OWNER_ADDRESS`, `RELAYER_ADDRESS`, `GOVERNOR_ADDRESS` diff --git a/src/evm/bridge-management/ownerRelayerGovernor.ts b/src/evm/bridge-management/ownerRelayerGovernor.ts new file mode 100644 index 0000000..14660b2 --- /dev/null +++ b/src/evm/bridge-management/ownerRelayerGovernor.ts @@ -0,0 +1,62 @@ +import { createBridgeManagementFromEnvironment, ensureEnv } from "../utils"; + +async function main() { + const action = process.env.MANAGEMENT_ACTION; + + const bridgeManagement = createBridgeManagementFromEnvironment(); + + switch (action) { + case 'transfer-ownership': { + const newOwner = process.env.NEW_OWNER; + if (!newOwner) return console.error('Missing NEW_OWNER'); + console.log('Transferring ownership to:', newOwner); + const tx = await bridgeManagement.transferOwnership(newOwner as `0x${string}`); + console.log('Transfer ownership transaction:', tx); + console.log('Note: The new owner must call accept-ownership to complete the transfer'); + break; + } + case 'accept-ownership': { + console.log('Accepting ownership transfer...'); + const tx = await bridgeManagement.acceptOwnership(); + console.log('Accept ownership transaction:', tx); + break; + } + case 'set-relayer': { + const newRelayer = process.env.NEW_RELAYER; + if (!newRelayer) return console.error('Missing NEW_RELAYER'); + console.log('Setting new relayer to:', newRelayer); + const tx = await bridgeManagement.setRelayer(newRelayer as `0x${string}`); + console.log('Set relayer transaction:', tx); + break; + } + case 'set-governor': { + const newGovernor = process.env.NEW_GOVERNOR; + if (!newGovernor) return console.error('Missing NEW_GOVERNOR'); + console.log('Setting new governor to:', newGovernor); + const tx = await bridgeManagement.setGovernor(newGovernor as `0x${string}`); + console.log('Set governor transaction:', tx); + break; + } + case 'set-security-guard': { + const newSecurityGuard = process.env.NEW_SECURITY_GUARD; + if (!newSecurityGuard) return console.error('Missing NEW_SECURITY_GUARD'); + console.log('Setting new security guard to:', newSecurityGuard); + const tx = await bridgeManagement.setSecurityGuard(newSecurityGuard as `0x${string}`); + console.log('Set security guard transaction:', tx); + break; + } + default: + console.error('Unknown action:', action); + console.log('Available actions: transfer-ownership, accept-ownership, set-relayer, set-governor, set-security-guard'); + } +} + +(async () => { + try { + ensureEnv(); + await main(); + } catch (error) { + console.error('Error executing owner/relayer/governor management script:', error); + process.exit(1); + } +})(); diff --git a/src/evm/bridge-management/validatorManagement.ts b/src/evm/bridge-management/validatorManagement.ts new file mode 100644 index 0000000..d52086e --- /dev/null +++ b/src/evm/bridge-management/validatorManagement.ts @@ -0,0 +1,62 @@ +import { createBridgeManagementFromEnvironment, ensureEnv } from "../utils"; + +async function main() { + const action = process.env.VALIDATOR_ACTION; + + const bridgeManagement = createBridgeManagementFromEnvironment(); + + switch (action) { + case 'add': { + const validator = process.env.VALIDATOR_ADDRESS; + if (!validator) return console.error('Missing VALIDATOR_ADDRESS'); + const incrementThreshold = process.env.INCREMENT_THRESHOLD === 'true'; + console.log('Adding validator:', validator, 'increment threshold:', incrementThreshold); + const tx = await bridgeManagement.addValidator(validator as `0x${string}`, incrementThreshold); + console.log('Add validator transaction:', tx); + break; + } + case 'remove': { + const validator = process.env.VALIDATOR_ADDRESS; + if (!validator) return console.error('Missing VALIDATOR_ADDRESS'); + const decrementThreshold = process.env.DECREMENT_THRESHOLD === 'true'; + console.log('Removing validator:', validator, 'decrement threshold:', decrementThreshold); + const tx = await bridgeManagement.removeValidator(validator as `0x${string}`, decrementThreshold); + console.log('Remove validator transaction:', tx); + break; + } + case 'replace': { + const oldValidator = process.env.OLD_VALIDATOR_ADDRESS; + const newValidator = process.env.NEW_VALIDATOR_ADDRESS; + if (!oldValidator || !newValidator) { + return console.error('Missing OLD_VALIDATOR_ADDRESS or NEW_VALIDATOR_ADDRESS'); + } + console.log('Replacing validator from:', oldValidator, 'to:', newValidator); + const tx = await bridgeManagement.replaceValidator(oldValidator as `0x${string}`, newValidator as `0x${string}`); + console.log('Replace validator transaction:', tx); + break; + } + case 'set-threshold': { + const threshold = Number(process.env.VALIDATOR_THRESHOLD); + if (isNaN(threshold) || threshold < 1) { + return console.error('Missing or invalid VALIDATOR_THRESHOLD (must be a positive number)'); + } + console.log('Setting validator threshold to:', threshold); + const tx = await bridgeManagement.setValidatorThreshold(BigInt(threshold)); + console.log('Set validator threshold transaction:', tx); + break; + } + default: + console.error('Unknown action:', action); + console.log('Available actions: add, remove, replace, set-threshold'); + } +} + +(async () => { + try { + ensureEnv(); + await main(); + } catch (error) { + console.error('Error executing validator management:', error); + process.exit(1); + } +})(); diff --git a/src/evm/message-bridge/README.md b/src/evm/message-bridge/README.md index 34acd22..8445e55 100644 --- a/src/evm/message-bridge/README.md +++ b/src/evm/message-bridge/README.md @@ -9,6 +9,7 @@ This directory contains examples for interacting with the EVM Message Bridge con - `readOnlyMethods.ts` - Read-only method calls to query message bridge state - `sendMessage.ts` - Send executable, result, or store-only messages - `setExecutionManager.ts` - Set the execution manager address +- `encodeExecutableMessage.ts` - Examples of encoding ERC20 balanceOf function calls for executable messages ## Available Scripts @@ -20,6 +21,7 @@ This directory contains examples for interacting with the EVM Message Bridge con - `npm run evm:amb:send-result` - Send a result message - `npm run evm:amb:send-store-only` - Send a store-only message - `npm run evm:amb:set-executor` - Set execution manager address +- `npm run evm:amb:encode-message` - Encode ERC20 balanceOf function calls for executable messages ## Required Environment Variables @@ -32,3 +34,7 @@ This directory contains examples for interacting with the EVM Message Bridge con - For `executeMessage.ts`: `MESSAGE_NONCE` (integer) - For `setExecutionManager.ts`: `EXECUTION_MANAGER_ADDRESS` - For `readOnlyMethods.ts`: Optional `MESSAGE_NONCE` (integer, defaults to 1 for testing) +- For `encodeExecutableMessage.ts`: + - `ERC20_TARGET` or `TARGET_CONTRACT_ADDRESS` (address) - Target ERC20 contract address (defaults to Neo token address) + - `ADDRESS` or `EVM_WALLET_ADDRESS` (address) - Address parameter for balanceOf function call + - `VALUE` (optional, wei amount) - Native token value to send (defaults to 0) diff --git a/src/evm/message-bridge/encodeExecutableMessage.ts b/src/evm/message-bridge/encodeExecutableMessage.ts new file mode 100644 index 0000000..f2a719b --- /dev/null +++ b/src/evm/message-bridge/encodeExecutableMessage.ts @@ -0,0 +1,200 @@ +import { createMessageBridgeFromEnvironment, ensureEnv } from "../utils"; +import { encodeFunctionData, encodeAbiParameters, isAddress } from 'viem'; + +async function encodeExecutableMessageExamples() { + console.log("\n--- Testing EVM Message Encoding for Executable Messages ---"); + + // Configuration from environment variables + const targetAddress = process.env.ADDRESS || process.env.EVM_WALLET_ADDRESS || "0x170c095a1a24958597177cb74044138c90944bcc"; + const erc20Address = process.env.ERC20_TARGET || process.env.TARGET_CONTRACT_ADDRESS || "0x05fd43b3eFcb4ff1CA08229cAEcf67Bc21D0C0a3"; + const value = BigInt(process.env.VALUE || "0"); + + console.log(`ERC20 Contract: ${erc20Address}`); + console.log(`Function: balanceOf(address)`); + console.log(`Target Address: ${targetAddress}`); + console.log(`Value: ${value.toString()}`); + + try { + console.log("\n--- Encoding EVM Function Call ---"); + + // Encode balanceOf function call using viem + const encodedCallData = encodeFunctionData({ + abi: [ + { + name: 'balanceOf', + type: 'function', + inputs: [{ name: 'account', type: 'address' }], + outputs: [{ name: '', type: 'uint256' }], + stateMutability: 'view' + } + ], + functionName: 'balanceOf', + args: [targetAddress as `0x${string}`] + }); + console.log("Encoded callData:", encodedCallData); + + // Encode as AMBTypes.Call structure using viem + const encodedEvmCall = encodeEvmCall(erc20Address, true, value, encodedCallData); + console.log("Encoded AMBTypes.Call:", encodedEvmCall); + + console.log("\n--- Testing Message Bridge State ---"); + + // Test current message bridge state using actual available methods + const messageBridge = createMessageBridgeFromEnvironment(); + const evmToNeoState = await messageBridge.evmToNeoState(); + console.log(`Current EVM to Neo state: nonce=${evmToNeoState.nonce}, root=${evmToNeoState.root}`); + + const neoToEvmState = await messageBridge.neoToEvmState(); + console.log(`Current Neo to EVM state: nonce=${neoToEvmState.nonce}, root=${neoToEvmState.root}`); + + const sendingPaused = await messageBridge.sendingPaused(); + console.log(`Sending paused: ${sendingPaused}`); + + const executingPaused = await messageBridge.executingPaused(); + console.log(`Executing paused: ${executingPaused}`); + + console.log("\n--- Testing View Function Call ---"); + + // Test the encoded call directly + await callViewFunction(erc20Address, encodedCallData); + + console.log("\n--- Contract Verification ---"); + + // Verify target is a contract + const isTargetContract = await isContract(erc20Address); + console.log(`Target address is contract: ${isTargetContract}`); + + console.log("\n--- Additional Encoding Examples ---"); + + // Show different encoding examples + await showEncodingExamples(); + + console.log("\n--- Message encoding completed ---"); + console.log("Note: This demonstrates how to encode function calls for cross-chain execution."); + console.log("The encoded data can be used in sendExecutableMessage calls."); + + } catch (error) { + console.error('Message encoding test failed:', error instanceof Error ? error.message : error); + } +} + +// Helper function to encode EVM call using viem +function encodeEvmCall(target: string, storeResult: boolean, value: bigint, callData: string): string { + // This mimics the AMBTypes.Call structure encoding using viem + return encodeAbiParameters( + [ + { name: 'target', type: 'address' }, + { name: 'storeResult', type: 'bool' }, + { name: 'value', type: 'uint256' }, + { name: 'callData', type: 'bytes' } + ], + [target as `0x${string}`, storeResult, value, callData as `0x${string}`] + ); +} + +// Test the encoded function call +async function callViewFunction(contractAddress: string, encodedCallData: string) { + try { + // Note: This would require a viem public client + // For now, we'll log what would be called + console.log(`Would call contract ${contractAddress} with data: ${encodedCallData}`); + console.log("Note: To actually execute this call, you would need a viem public client"); + console.log("Example: const result = await publicClient.call({ to: contractAddress, data: encodedCallData });"); + } catch (error) { + console.log("Could not test view function call:", error instanceof Error ? error.message : error); + } +} + +// Check if address is a contract using viem +async function isContract(address: string): Promise { + try { + // Use viem's address validation + const isValidAddress = isAddress(address); + console.log(`Address validation: ${isValidAddress}`); + return isValidAddress; + } catch (error) { + console.log("Could not verify contract:", error instanceof Error ? error.message : error); + return false; + } +} + +// Show various encoding examples using viem +async function showEncodingExamples() { + console.log("--- Additional Encoding Examples ---"); + + // Example 1: ERC20 transfer + try { + const transferData = encodeFunctionData({ + abi: [ + { + name: 'transfer', + type: 'function', + inputs: [ + { name: 'to', type: 'address' }, + { name: 'amount', type: 'uint256' } + ], + outputs: [{ name: '', type: 'bool' }], + stateMutability: 'nonpayable' + } + ], + functionName: 'transfer', + args: ['0x170c095a1a24958597177cb74044138c90944bcc' as `0x${string}`, BigInt('1000000000000000000')] + }); + console.log("ERC20 transfer encoded data:", transferData); + } catch (error) { + console.log("Transfer encoding example failed:", error instanceof Error ? error.message : error); + } + + // Example 2: Simple contract call with no parameters + try { + const totalSupplyData = encodeFunctionData({ + abi: [ + { + name: 'totalSupply', + type: 'function', + inputs: [], + outputs: [{ name: '', type: 'uint256' }], + stateMutability: 'view' + } + ], + functionName: 'totalSupply', + args: [] + }); + console.log("ERC20 totalSupply encoded data:", totalSupplyData); + } catch (error) { + console.log("TotalSupply encoding example failed:", error instanceof Error ? error.message : error); + } + + // Example 3: Contract call with multiple parameters + try { + const approveData = encodeFunctionData({ + abi: [ + { + name: 'approve', + type: 'function', + inputs: [ + { name: 'spender', type: 'address' }, + { name: 'amount', type: 'uint256' } + ], + outputs: [{ name: '', type: 'bool' }], + stateMutability: 'nonpayable' + } + ], + functionName: 'approve', + args: ['0x170c095a1a24958597177cb74044138c90944bcc' as `0x${string}`, BigInt('1000000000000000000')] + }); + console.log("ERC20 approve encoded data:", approveData); + } catch (error) { + console.log("Approve encoding example failed:", error instanceof Error ? error.message : error); + } +} + +(async () => { + try { + ensureEnv(); + await encodeExecutableMessageExamples(); + } catch (error) { + console.error('Error in message encoding examples:', error); + process.exit(1); + } +})(); diff --git a/src/evm/native-bridge/README.md b/src/evm/native-bridge/README.md index c461c83..c46b108 100644 --- a/src/evm/native-bridge/README.md +++ b/src/evm/native-bridge/README.md @@ -4,12 +4,27 @@ This directory contains examples for interacting with the EVM Native Bridge cont ## Files -- `readOnlyMethods.ts` - Read-only method calls to query native bridge state and configuration +- `nativeBridgeOperations.ts` - Native bridge management operations (set, deposit, claim, pause/unpause, fee management) +- `pauseOperations.ts` - Bridge and deposits pause/unpause operations testing +- `readOnlyMethods.ts` - Comprehensive read-only queries for bridge state, configuration, and NEP-17 token balances ## Available Scripts ### Native Bridge Operations -- `npm run evm:nb:readonly` - Read all native bridge state information +- `npm run evm:nb:operations` - Interactive operations based on NATIVE_OPERATION env var +- `npm run evm:nb:readonly` - Display comprehensive bridge state, configuration, and NEP-17 token balances +- `npm run evm:nb:pause` - Test pause/unpause operations + +### Specific Native Operations +- `npm run evm:nb:set` - Set native bridge configuration +- `npm run evm:nb:deposit` - Deposit native tokens +- `npm run evm:nb:claim` - Claim native tokens +- `npm run evm:nb:pause-bridge` - Pause the native bridge +- `npm run evm:nb:unpause-bridge` - Unpause the native bridge +- `npm run evm:nb:set-fee` - Set native deposit fee +- `npm run evm:nb:set-min` - Set minimum native deposit amount +- `npm run evm:nb:set-max` - Set maximum native deposit amount +- `npm run evm:nb:set-total` - Set maximum total deposited native amount ## Required Environment Variables diff --git a/src/evm/native-bridge/nativeBridgeOperations.ts b/src/evm/native-bridge/nativeBridgeOperations.ts new file mode 100644 index 0000000..c60cc1b --- /dev/null +++ b/src/evm/native-bridge/nativeBridgeOperations.ts @@ -0,0 +1,165 @@ +import { createNativeBridgeFromEnvironment, ensureEnv } from "../utils"; + +async function nativeBridgeOperations() { + const operation = process.env.NATIVE_OPERATION; + if (!operation) { + console.error("Set NATIVE_OPERATION environment variable to specify operation."); + console.log("Available operations: set, deposit, claim, pause-bridge, unpause-bridge, set-fee, set-min, set-max, set-total"); + return; + } + + const nativeBridge = createNativeBridgeFromEnvironment(); + + try { + switch (operation) { + case 'set': + await setNativeBridge(nativeBridge); + break; + case 'deposit': + await depositNative(nativeBridge); + break; + case 'claim': + await claimNative(nativeBridge); + break; + case 'pause-bridge': + await pauseNativeBridge(nativeBridge); + break; + case 'unpause-bridge': + await unpauseNativeBridge(nativeBridge); + break; + case 'set-fee': + await setNativeDepositFee(nativeBridge); + break; + case 'set-min': + await setMinNativeDeposit(nativeBridge); + break; + case 'set-max': + await setMaxNativeDeposit(nativeBridge); + break; + case 'set-total': + await setMaxTotalDepositedNative(nativeBridge); + break; + default: + console.error(`Unknown operation: ${operation}`); + console.log("Available operations: set, deposit, claim, pause-bridge, unpause-bridge, set-fee, set-min, set-max, set-total"); + } + } catch (error) { + console.error(`Failed to execute ${operation}:`, error); + } +} + +async function setNativeBridge(nativeBridge: any) { + const neoTokenAddress = process.env.NEO_TOKEN_ADDRESS; + const decimals = Number(process.env.NATIVE_DECIMALS || '18'); + + if (!neoTokenAddress) { + console.error('Missing NEO_TOKEN_ADDRESS'); + return; + } + + console.log('Setting native bridge with Neo token address:', neoTokenAddress); + const tx = await nativeBridge.write.setNativeBridge([neoTokenAddress, decimals]); + console.log('Set native bridge transaction:', tx); +} + +async function depositNative(nativeBridge: any) { + const amount = process.env.NATIVE_AMOUNT; + const recipient = process.env.NATIVE_RECIPIENT; + + if (!amount || !recipient) { + console.error('Missing NATIVE_AMOUNT or NATIVE_RECIPIENT'); + return; + } + + console.log(`Depositing ${amount} native tokens to recipient: ${recipient}`); + const tx = await nativeBridge.write.depositNative([recipient], { value: BigInt(amount) }); + console.log('Deposit native transaction:', tx); +} + +async function claimNative(nativeBridge: any) { + const nonce = Number(process.env.NATIVE_CLAIM_NONCE); + const proof = process.env.NATIVE_CLAIM_PROOF; + + if (!nonce || !proof) { + console.error('Missing NATIVE_CLAIM_NONCE or NATIVE_CLAIM_PROOF'); + return; + } + + console.log(`Claiming native tokens for nonce: ${nonce}`); + const tx = await nativeBridge.write.claimNative([nonce, proof]); + console.log('Claim native transaction:', tx); +} + +async function pauseNativeBridge(nativeBridge: any) { + console.log('Pausing native bridge...'); + const tx = await nativeBridge.write.pauseNativeBridge(); + console.log('Pause native bridge transaction:', tx); +} + +async function unpauseNativeBridge(nativeBridge: any) { + console.log('Unpausing native bridge...'); + const tx = await nativeBridge.write.unpauseNativeBridge(); + console.log('Unpause native bridge transaction:', tx); +} + +async function setNativeDepositFee(nativeBridge: any) { + const fee = process.env.NATIVE_DEPOSIT_FEE; + + if (!fee) { + console.error('Missing NATIVE_DEPOSIT_FEE'); + return; + } + + console.log(`Setting native deposit fee to: ${fee}`); + const tx = await nativeBridge.write.setNativeDepositFee([BigInt(fee)]); + console.log('Set native deposit fee transaction:', tx); +} + +async function setMinNativeDeposit(nativeBridge: any) { + const minAmount = process.env.NATIVE_MIN_DEPOSIT; + + if (!minAmount) { + console.error('Missing NATIVE_MIN_DEPOSIT'); + return; + } + + console.log(`Setting minimum native deposit to: ${minAmount}`); + const tx = await nativeBridge.write.setMinNativeDeposit([BigInt(minAmount)]); + console.log('Set minimum native deposit transaction:', tx); +} + +async function setMaxNativeDeposit(nativeBridge: any) { + const maxAmount = process.env.NATIVE_MAX_DEPOSIT; + + if (!maxAmount) { + console.error('Missing NATIVE_MAX_DEPOSIT'); + return; + } + + console.log(`Setting maximum native deposit to: ${maxAmount}`); + const tx = await nativeBridge.write.setMaxNativeDeposit([BigInt(maxAmount)]); + console.log('Set maximum native deposit transaction:', tx); +} + +async function setMaxTotalDepositedNative(nativeBridge: any) { + const maxTotal = process.env.NATIVE_MAX_TOTAL_DEPOSIT; + + if (!maxTotal) { + console.error('Missing NATIVE_MAX_TOTAL_DEPOSIT'); + return; + } + + console.log(`Setting maximum total deposited native to: ${maxTotal}`); + const tx = await nativeBridge.write.setMaxTotalDepositedNative([BigInt(maxTotal)]); + console.log('Set maximum total deposited native transaction:', tx); +} + +(async () => { + try { + ensureEnv(); + await nativeBridgeOperations(); + } catch (error) { + console.error('Error executing native bridge operations:', error); + process.exit(1); + } +})(); diff --git a/src/evm/native-bridge/pauseOperations.ts b/src/evm/native-bridge/pauseOperations.ts new file mode 100644 index 0000000..c7af6ba --- /dev/null +++ b/src/evm/native-bridge/pauseOperations.ts @@ -0,0 +1,94 @@ +import { createNativeBridgeFromEnvironment, ensureEnv } from "../utils"; + +async function performPauseOperations() { + console.log("\n--- Testing EVM Native Bridge Pause/Unpause Operations ---"); + + const nativeBridge = createNativeBridgeFromEnvironment(); + + try { + console.log("\n1. Initial State Check:"); + let bridgePaused = await logBridgePauseState(nativeBridge); + let nativePaused = await logNativePauseState(nativeBridge); + + console.log("\n2. Testing native bridge pause/unpause..."); + if (!nativePaused) { + console.log("Attempting to pause native bridge..."); + const tx = await nativeBridge.pauseNativeBridge(); + console.log(`Pause native bridge transaction: ${tx}`); + + // Wait a moment for the transaction to be mined + await new Promise(resolve => setTimeout(resolve, 2000)); + nativePaused = await logNativePauseState(nativeBridge); + } + + if (nativePaused) { + console.log("Attempting to unpause native bridge..."); + const tx = await nativeBridge.unpauseNativeBridge(); + console.log(`Unpause native bridge transaction: ${tx}`); + + // Wait a moment for the transaction to be mined + await new Promise(resolve => setTimeout(resolve, 2000)); + await logNativePauseState(nativeBridge); + } + + console.log("\n3. Testing general bridge pause/unpause..."); + if (!bridgePaused) { + console.log("Attempting to pause bridge..."); + const tx = await nativeBridge.pauseBridge(); + console.log(`Pause bridge transaction: ${tx}`); + + // Wait a moment for the transaction to be mined + await new Promise(resolve => setTimeout(resolve, 2000)); + bridgePaused = await logBridgePauseState(nativeBridge); + } + + if (bridgePaused) { + console.log("Attempting to unpause bridge..."); + const tx = await nativeBridge.unpauseBridge(); + console.log(`Unpause bridge transaction: ${tx}`); + + // Wait a moment for the transaction to be mined + await new Promise(resolve => setTimeout(resolve, 2000)); + await logBridgePauseState(nativeBridge); + } + + console.log("\n4. Final State Check:"); + await logBridgePauseState(nativeBridge); + await logNativePauseState(nativeBridge); + + } catch (error) { + console.error('Pause operations test failed:', error instanceof Error ? error.message : error); + } +} + +async function logBridgePauseState(nativeBridge: any): Promise { + try { + const bridgePaused = await nativeBridge.bridgePaused(); + console.log(` Bridge Paused: ${bridgePaused}`); + return bridgePaused; + } catch (error) { + console.error(' Failed to get bridge pause state:', error instanceof Error ? error.message : error); + return false; + } +} + +async function logNativePauseState(nativeBridge: any): Promise { + try { + const nativePaused = await nativeBridge.nativeBridgePaused(); + console.log(` Native Bridge Paused: ${nativePaused}`); + return nativePaused; + } catch (error) { + console.error(' Failed to get native bridge pause state:', error instanceof Error ? error.message : error); + return false; + } +} + +(async () => { + try { + ensureEnv(); + await performPauseOperations(); + } catch (error) { + console.error('Error in native bridge pause operations:', error); + process.exit(1); + } +})(); diff --git a/src/evm/token-bridge/README.md b/src/evm/token-bridge/README.md index 7f53aa5..54d7478 100644 --- a/src/evm/token-bridge/README.md +++ b/src/evm/token-bridge/README.md @@ -4,13 +4,26 @@ This directory contains examples for interacting with the EVM Token Bridge contr ## Files +- `tokenBridgeOperations.ts` - Token bridge management operations (register, deposit, claim, pause/unpause, fee management) - `readOnlyMethods.ts` - Read-only method calls to query token bridge state and configuration ## Available Scripts ### Token Bridge Operations +- `npm run evm:tb:operations` - Interactive operations based on TOKEN_OPERATION env var - `npm run evm:tb:readonly` - Read all token bridge state information +### Specific Token Operations +- `npm run evm:tb:register` - Register a new token +- `npm run evm:tb:deposit` - Deposit tokens +- `npm run evm:tb:claim` - Claim tokens +- `npm run evm:tb:pause` - Pause token bridge for a specific token +- `npm run evm:tb:unpause` - Unpause token bridge for a specific token +- `npm run evm:tb:set-fee` - Set token deposit fee +- `npm run evm:tb:set-min` - Set minimum token deposit amount +- `npm run evm:tb:set-max` - Set maximum token deposit amount +- `npm run evm:tb:set-withdrawals` - Set maximum token withdrawals + ## Required Environment Variables - `EVM_TOKEN_BRIDGE_CONTRACT_ADDRESS` - Contract address of the EVM Token Bridge diff --git a/src/evm/token-bridge/tokenBridgeOperations.ts b/src/evm/token-bridge/tokenBridgeOperations.ts new file mode 100644 index 0000000..74be5c8 --- /dev/null +++ b/src/evm/token-bridge/tokenBridgeOperations.ts @@ -0,0 +1,188 @@ +import { createTokenBridgeFromEnvironment, ensureEnv } from "../utils"; + +async function tokenBridgeOperations() { + console.log("\n--- Testing EVM Token Bridge Operations ---"); + + const operation = process.env.TOKEN_OPERATION; + if (!operation) { + console.log("Set TOKEN_OPERATION environment variable to specify operation."); + console.log("Available operations: register, deposit, claim, pause, unpause, set-fee, set-min, set-max, set-withdrawals"); + return; + } + + const tokenBridge = createTokenBridgeFromEnvironment(); + + try { + switch (operation) { + case 'register': + await registerToken(tokenBridge); + break; + case 'deposit': + await depositToken(tokenBridge); + break; + case 'claim': + await claimToken(tokenBridge); + break; + case 'pause': + await pauseTokenBridge(tokenBridge); + break; + case 'unpause': + await unpauseTokenBridge(tokenBridge); + break; + case 'set-fee': + await setTokenDepositFee(tokenBridge); + break; + case 'set-min': + await setMinTokenDeposit(tokenBridge); + break; + case 'set-max': + await setMaxTokenDeposit(tokenBridge); + break; + case 'set-withdrawals': + await setMaxTokenWithdrawals(tokenBridge); + break; + default: + console.error(`Unknown operation: ${operation}`); + console.log("Available operations: register, deposit, claim, pause, unpause, set-fee, set-min, set-max, set-withdrawals"); + } + } catch (error) { + console.error(`Failed to execute ${operation}:`, error); + } +} + +async function registerToken(tokenBridge: any) { + const tokenAddress = process.env.TOKEN_ADDRESS; + const neoTokenHash = process.env.NEO_TOKEN_HASH; + const decimals = Number(process.env.TOKEN_DECIMALS || '18'); + + if (!tokenAddress || !neoTokenHash) { + console.error('Missing TOKEN_ADDRESS or NEO_TOKEN_HASH'); + return; + } + + console.log(`Registering token ${tokenAddress} with Neo hash ${neoTokenHash}`); + const tx = await tokenBridge.registerToken(tokenAddress, neoTokenHash, decimals); + console.log('Register token transaction:', tx); +} + +async function depositToken(tokenBridge: any) { + const tokenAddress = process.env.TOKEN_ADDRESS; + const amount = process.env.TOKEN_AMOUNT; + const recipient = process.env.TOKEN_RECIPIENT; + + if (!tokenAddress || !amount || !recipient) { + console.error('Missing TOKEN_ADDRESS, TOKEN_AMOUNT, or TOKEN_RECIPIENT'); + return; + } + + console.log(`Depositing ${amount} of token ${tokenAddress} to recipient: ${recipient}`); + const tx = await tokenBridge.depositToken(tokenAddress, BigInt(amount), recipient); + console.log('Deposit token transaction:', tx); +} + +async function claimToken(tokenBridge: any) { + const tokenAddress = process.env.TOKEN_ADDRESS; + const nonce = Number(process.env.TOKEN_CLAIM_NONCE); + const proof = process.env.TOKEN_CLAIM_PROOF; + + if (!tokenAddress || !nonce || !proof) { + console.error('Missing TOKEN_ADDRESS, TOKEN_CLAIM_NONCE, or TOKEN_CLAIM_PROOF'); + return; + } + + console.log(`Claiming tokens for ${tokenAddress} at nonce: ${nonce}`); + const tx = await tokenBridge.claimToken(tokenAddress, nonce, proof); + console.log('Claim token transaction:', tx); +} + +async function pauseTokenBridge(tokenBridge: any) { + const tokenAddress = process.env.TOKEN_ADDRESS; + + if (!tokenAddress) { + console.error('Missing TOKEN_ADDRESS'); + return; + } + + console.log(`Pausing token bridge for ${tokenAddress}...`); + const tx = await tokenBridge.pauseTokenBridge(tokenAddress); + console.log('Pause token bridge transaction:', tx); +} + +async function unpauseTokenBridge(tokenBridge: any) { + const tokenAddress = process.env.TOKEN_ADDRESS; + + if (!tokenAddress) { + console.error('Missing TOKEN_ADDRESS'); + return; + } + + console.log(`Unpausing token bridge for ${tokenAddress}...`); + const tx = await tokenBridge.unpauseTokenBridge(tokenAddress); + console.log('Unpause token bridge transaction:', tx); +} + +async function setTokenDepositFee(tokenBridge: any) { + const tokenAddress = process.env.TOKEN_ADDRESS; + const fee = process.env.TOKEN_DEPOSIT_FEE; + + if (!tokenAddress || !fee) { + console.error('Missing TOKEN_ADDRESS or TOKEN_DEPOSIT_FEE'); + return; + } + + console.log(`Setting deposit fee for ${tokenAddress} to: ${fee}`); + const tx = await tokenBridge.setTokenDepositFee(tokenAddress, BigInt(fee)); + console.log('Set token deposit fee transaction:', tx); +} + +async function setMinTokenDeposit(tokenBridge: any) { + const tokenAddress = process.env.TOKEN_ADDRESS; + const minAmount = process.env.TOKEN_MIN_DEPOSIT; + + if (!tokenAddress || !minAmount) { + console.error('Missing TOKEN_ADDRESS or TOKEN_MIN_DEPOSIT'); + return; + } + + console.log(`Setting minimum deposit for ${tokenAddress} to: ${minAmount}`); + const tx = await tokenBridge.setMinTokenDeposit(tokenAddress, BigInt(minAmount)); + console.log('Set minimum token deposit transaction:', tx); +} + +async function setMaxTokenDeposit(tokenBridge: any) { + const tokenAddress = process.env.TOKEN_ADDRESS; + const maxAmount = process.env.TOKEN_MAX_DEPOSIT; + + if (!tokenAddress || !maxAmount) { + console.error('Missing TOKEN_ADDRESS or TOKEN_MAX_DEPOSIT'); + return; + } + + console.log(`Setting maximum deposit for ${tokenAddress} to: ${maxAmount}`); + const tx = await tokenBridge.setMaxTokenDeposit(tokenAddress, BigInt(maxAmount)); + console.log('Set maximum token deposit transaction:', tx); +} + +async function setMaxTokenWithdrawals(tokenBridge: any) { + const tokenAddress = process.env.TOKEN_ADDRESS; + const maxWithdrawals = process.env.TOKEN_MAX_WITHDRAWALS; + + if (!tokenAddress || !maxWithdrawals) { + console.error('Missing TOKEN_ADDRESS or TOKEN_MAX_WITHDRAWALS'); + return; + } + + console.log(`Setting maximum withdrawals for ${tokenAddress} to: ${maxWithdrawals}`); + const tx = await tokenBridge.setMaxTokenWithdrawals(tokenAddress, Number(maxWithdrawals)); + console.log('Set maximum token withdrawals transaction:', tx); +} + +(async () => { + try { + ensureEnv(); + await tokenBridgeOperations(); + } catch (error) { + console.error('Error executing token bridge operations:', error); + process.exit(1); + } +})(); diff --git a/src/evm/utils.ts b/src/evm/utils.ts index 7d95208..0584e81 100644 --- a/src/evm/utils.ts +++ b/src/evm/utils.ts @@ -4,7 +4,8 @@ import { EvmExecutionManager, EvmNativeBridge, EvmTokenBridge, - EvmBridgeManagement, EvmMessageBridgeBuilder, EvmNativeBridgeBuilder, EvmTokenBridgeBuilder + EvmBridgeManagement, EvmMessageBridgeFactory, EvmNativeBridgeFactory, EvmTokenBridgeFactory, + EvmExecutionManagerFactory, EvmBridgeManagementFactory } from "@bane-labs/bridge-sdk-ts"; import { createPublicClient, createWalletClient, http, type Address } from 'viem'; import { privateKeyToAccount } from 'viem/accounts'; @@ -48,7 +49,7 @@ export function createMessageBridgeFromEnvironment(): EvmMessageBridge { } const config = createEvmContractWrapperConfig(contractAddress as Address); - return EvmMessageBridgeBuilder.create(config); + return EvmMessageBridgeFactory.create(config); } export function createExecutionManagerFromEnvironment(): EvmExecutionManager { @@ -58,7 +59,7 @@ export function createExecutionManagerFromEnvironment(): EvmExecutionManager { } const config = createEvmContractWrapperConfig(contractAddress as Address); - return new EvmExecutionManager(config); + return EvmExecutionManagerFactory.create(config); } export function createNativeBridgeFromEnvironment(): EvmNativeBridge { @@ -68,7 +69,7 @@ export function createNativeBridgeFromEnvironment(): EvmNativeBridge { } const config = createEvmContractWrapperConfig(contractAddress as Address); - return EvmNativeBridgeBuilder.create(config); + return EvmNativeBridgeFactory.create(config); } export function createTokenBridgeFromEnvironment(): EvmTokenBridge { @@ -78,7 +79,7 @@ export function createTokenBridgeFromEnvironment(): EvmTokenBridge { } const config = createEvmContractWrapperConfig(contractAddress as Address); - return EvmTokenBridgeBuilder.create(config); + return EvmTokenBridgeFactory.create(config); } export function createBridgeManagementFromEnvironment(): EvmBridgeManagement { @@ -88,7 +89,7 @@ export function createBridgeManagementFromEnvironment(): EvmBridgeManagement { } const config = createEvmContractWrapperConfig(contractAddress as Address); - return new EvmBridgeManagement(config); + return EvmBridgeManagementFactory.create(config); } export function requireEnvVar(name: string): string { diff --git a/src/neo/execution-manager/README.md b/src/neo/execution-manager/README.md index 62cb03a..b642a59 100644 --- a/src/neo/execution-manager/README.md +++ b/src/neo/execution-manager/README.md @@ -12,10 +12,11 @@ This directory contains examples for interacting with the ExecutionManager contr ## Available Scripts ### Execution Manager Operations -- `npm run em:execute` - Execute a message using MESSAGE_NONCE and EXECUTABLE_CODE -- `npm run em:readonly` - Read all execution manager state information -- `npm run em:pause` - Test pause/unpause operations -- `npm run em:serialize` - Test serialization and validation methods +- `npm run neo:em:execute` - Execute a message using MESSAGE_NONCE and EXECUTABLE_CODE +- `npm run neo:em:readonly` - Read all execution manager state information +- `npm run neo:em:pause` - Test pause/unpause operations +- `npm run neo:em:serialize` - Test serialization and validation methods +- `npm run neo:em:serialize-pause` - Test serialization of isPaused method ## Required Environment Variables diff --git a/src/neo/management/README.md b/src/neo/management/README.md index 2b275fb..e605bae 100644 --- a/src/neo/management/README.md +++ b/src/neo/management/README.md @@ -11,19 +11,17 @@ This directory contains examples for interacting with the Management contract, w ## Available Scripts ### Management Operations -- `npm run mg:owner` - Set owner/relayer/governor/security guard based on MANAGEMENT_ACTION -- `npm run mg:readonly` - Read all management state information -- `npm run mg:validator` - Manage validators based on VALIDATOR_ACTION +- `npm run neo:mgmt:readonly` - Read all management state information +- `npm run neo:mgmt:validator-add` - Add a validator +- `npm run neo:mgmt:validator-remove` - Remove a validator +- `npm run neo:mgmt:validator-replace` - Replace a validator +- `npm run neo:mgmt:validator-threshold` - Set validator threshold ### Specific Management Operations -- `npm run mg:set-owner` - Set new owner -- `npm run mg:set-relayer` - Set new relayer -- `npm run mg:set-governor` - Set new governor -- `npm run mg:set-security-guard` - Set new security guard -- `npm run mg:add-validator` - Add a validator -- `npm run mg:remove-validator` - Remove a validator -- `npm run mg:replace-validator` - Replace a validator -- `npm run mg:set-threshold` - Set validator threshold +- `npm run neo:mgmt:set-owner` - Set new owner +- `npm run neo:mgmt:set-relayer` - Set new relayer +- `npm run neo:mgmt:set-governor` - Set new governor +- `npm run neo:mgmt:set-security` - Set new security guard ## Required Environment Variables diff --git a/src/neo/message-bridge/README.md b/src/neo/message-bridge/README.md index 455eab0..0344509 100644 --- a/src/neo/message-bridge/README.md +++ b/src/neo/message-bridge/README.md @@ -14,17 +14,16 @@ This directory contains examples for interacting with the Message Bridge contrac ## Available Scripts ### Message Bridge Operations -- `npm run amb:execute` - Execute a message using MESSAGE_NONCE -- `npm run amb:readonly` - Read all message bridge state information -- `npm run amb:pause` - Test all pause/unpause operations -- `npm run amb:send` - Send messages based on MESSAGE_BRIDGE_OPERATION -- `npm run amb:serialize` - Test serialization and validation methods -- `npm run amb:set-execution-manager` - Set execution manager address +- `npm run neo:amb:execute` - Execute a message using MESSAGE_NONCE +- `npm run neo:amb:readonly` - Read all message bridge state information +- `npm run neo:amb:pause` - Test all pause/unpause operations +- `npm run neo:amb:serialize` - Test serialization and validation methods +- `npm run neo:amb:set-executor` - Set execution manager address ### Specific Message Operations -- `npm run amb:send-executable` - Send an executable message -- `npm run amb:send-result` - Send a result message -- `npm run amb:send-store-only` - Send a store-only message +- `npm run neo:amb:send-executable` - Send an executable message +- `npm run neo:amb:send-result` - Send a result message +- `npm run neo:amb:send-store-only` - Send a store-only message ## Required Environment Variables diff --git a/src/neo/message-bridge/sendMessage.ts b/src/neo/message-bridge/sendMessage.ts index c30ec94..0d57c1a 100644 --- a/src/neo/message-bridge/sendMessage.ts +++ b/src/neo/message-bridge/sendMessage.ts @@ -1,9 +1,9 @@ import { NeoGenericError, NeoMessageBridge, - type SendExecutableMessageParams, - type SendResultMessageParams, - type SendStoreOnlyMessageParams + type NeoSendExecutableMessageParams, + type NeoSendResultMessageParams, + type NeoSendStoreOnlyMessageParams } from "@bane-labs/bridge-sdk-ts"; import { createMessageBridgeFromEnvironment, ensureEnv } from "../utils"; @@ -17,7 +17,7 @@ async function sendExecutableMessage(messageBridge: NeoMessageBridge) { const sendingFee = await messageBridge.sendingFee(); - const params: SendExecutableMessageParams = { + const params: NeoSendExecutableMessageParams = { messageData, storeResult, maxFee: sendingFee @@ -35,7 +35,7 @@ async function sendResultMessage(messageBridge: NeoMessageBridge) { const sendingFee = await messageBridge.sendingFee(); - const params: SendResultMessageParams = { + const params: NeoSendResultMessageParams = { nonce: parseInt(nonce, 10), maxFee: sendingFee }; @@ -52,7 +52,7 @@ async function sendStoreOnlyMessage(messageBridge: NeoMessageBridge) { const sendingFee = await messageBridge.sendingFee(); - const params: SendStoreOnlyMessageParams = { + const params: NeoSendStoreOnlyMessageParams = { messageData, maxFee: sendingFee }; diff --git a/src/neo/native-bridge/README.md b/src/neo/native-bridge/README.md index 8927da4..151d336 100644 --- a/src/neo/native-bridge/README.md +++ b/src/neo/native-bridge/README.md @@ -11,20 +11,20 @@ This directory contains examples for interacting with the Native Bridge contract ## Available Scripts ### Native Bridge Operations -- `npm run nb:operations` - Interactive operations based on NATIVE_OPERATION env var -- `npm run nb:readonly` - Display comprehensive bridge state, configuration, and NEP-17 token balances -- `npm run nb:pause` - Test pause/unpause operations +- `npm run neo:nb:operations` - Interactive operations based on NATIVE_OPERATION env var +- `npm run neo:nb:readonly` - Display comprehensive bridge state, configuration, and NEP-17 token balances +- `npm run neo:nb:pause` - Test pause/unpause operations ### Specific Native Operations -- `npm run nb:set` - Set native bridge configuration -- `npm run nb:deposit` - Deposit native tokens -- `npm run nb:claim` - Claim native tokens -- `npm run nb:pause-bridge` - Pause the native bridge -- `npm run nb:unpause-bridge` - Unpause the native bridge -- `npm run nb:set-fee` - Set native deposit fee -- `npm run nb:set-min` - Set minimum native deposit amount -- `npm run nb:set-max` - Set maximum native deposit amount -- `npm run nb:set-total` - Set maximum total deposited native amount +- `npm run neo:nb:set` - Set native bridge configuration +- `npm run neo:nb:deposit` - Deposit native tokens +- `npm run neo:nb:claim` - Claim native tokens +- `npm run neo:nb:pause-bridge` - Pause the native bridge +- `npm run neo:nb:unpause-bridge` - Unpause the native bridge +- `npm run neo:nb:set-fee` - Set native deposit fee +- `npm run neo:nb:set-min` - Set minimum native deposit amount +- `npm run neo:nb:set-max` - Set maximum native deposit amount +- `npm run neo:nb:set-total` - Set maximum total deposited native amount ## Required Environment Variables diff --git a/src/neo/token-bridge/README.md b/src/neo/token-bridge/README.md index 20ba4a7..775da6d 100644 --- a/src/neo/token-bridge/README.md +++ b/src/neo/token-bridge/README.md @@ -10,19 +10,19 @@ This directory contains examples for interacting with the Token Bridge contract, ## Available Scripts ### Token Bridge Operations -- `npm run tb:operations` - Interactive operations based on TOKEN_OPERATION env var -- `npm run tb:readonly` - Read all token bridge state information +- `npm run neo:tb:operations` - Interactive operations based on TOKEN_OPERATION env var +- `npm run neo:tb:readonly` - Read all token bridge state information ### Specific Token Operations -- `npm run tb:register` - Register a new token -- `npm run tb:deposit` - Deposit tokens -- `npm run tb:claim` - Claim tokens -- `npm run tb:pause` - Pause token bridge for a specific token -- `npm run tb:unpause` - Unpause token bridge for a specific token -- `npm run tb:set-fee` - Set token deposit fee -- `npm run tb:set-min` - Set minimum token deposit amount -- `npm run tb:set-max` - Set maximum token deposit amount -- `npm run tb:set-withdrawals` - Set maximum token withdrawals +- `npm run neo:tb:register` - Register a new token +- `npm run neo:tb:deposit` - Deposit tokens +- `npm run neo:tb:claim` - Claim tokens +- `npm run neo:tb:pause` - Pause token bridge for a specific token +- `npm run neo:tb:unpause` - Unpause token bridge for a specific token +- `npm run neo:tb:set-fee` - Set token deposit fee +- `npm run neo:tb:set-min` - Set minimum token deposit amount +- `npm run neo:tb:set-max` - Set maximum token deposit amount +- `npm run neo:tb:set-withdrawals` - Set maximum token withdrawals ## Required Environment Variables diff --git a/src/neo/wallet/README.md b/src/neo/wallet/README.md index 822f9d7..1967531 100644 --- a/src/neo/wallet/README.md +++ b/src/neo/wallet/README.md @@ -9,7 +9,7 @@ This directory contains examples for interacting with Neo wallets, including loa ## Available Scripts ### Wallet Operations -- `npm run wallet` - Run wallet operations (load, decrypt, display balances, etc.) +- `npm run neo:wallet` - Run wallet operations (load, decrypt, display balances, etc.) ## Required Environment Variables diff --git a/tsconfig.json b/tsconfig.json index bd912d6..d1b25ec 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -3,7 +3,7 @@ "target": "ES2022", "module": "ESNext", "moduleResolution": "node", - "lib": ["ES2022"], + "lib": ["ES2022", "DOM", "DOM.Iterable"], "outDir": "./dist", "rootDir": "./", "strict": true, From 44b1c7f37be305bca34041b3db58012b6f982a7c Mon Sep 17 00:00:00 2001 From: Otniel Nicola Date: Fri, 30 Jan 2026 16:18:29 +0200 Subject: [PATCH 5/8] chore: Update env vars names --- README.md | 7 +- env-template | 23 +++- package-lock.json | 113 +++++++++++++++++- package.json | 1 + src/evm/README.md | 5 +- src/evm/bridge-management/README.md | 3 +- .../bridge-management/ownerRelayerGovernor.ts | 2 +- src/evm/bridge-management/readOnlyMethods.ts | 2 +- .../bridge-management/validatorManagement.ts | 2 +- src/evm/execution-manager/README.md | 3 +- src/evm/execution-manager/executeMessage.ts | 6 +- src/evm/execution-manager/readOnlyMethods.ts | 2 +- src/evm/message-bridge/README.md | 3 +- .../message-bridge/encodeExecutableMessage.ts | 2 +- src/evm/message-bridge/executeMessage.ts | 6 +- src/evm/message-bridge/pauseOperations.ts | 6 +- src/evm/message-bridge/readOnlyMethods.ts | 2 +- src/evm/message-bridge/sendMessage.ts | 22 ++-- src/evm/message-bridge/setExecutionManager.ts | 6 +- src/evm/native-bridge/README.md | 3 +- .../native-bridge/nativeBridgeOperations.ts | 2 +- src/evm/native-bridge/pauseOperations.ts | 2 +- src/evm/native-bridge/readOnlyMethods.ts | 2 +- src/evm/token-bridge/README.md | 3 +- src/evm/token-bridge/readOnlyMethods.ts | 2 +- src/evm/token-bridge/tokenBridgeOperations.ts | 2 +- src/evm/utils.ts | 67 +++++++---- src/neo/execution-manager/README.md | 4 +- src/neo/execution-manager/readOnlyMethods.ts | 4 +- src/neo/management/README.md | 4 +- src/neo/message-bridge/README.md | 4 +- src/neo/native-bridge/README.md | 4 +- src/neo/native-bridge/readOnlyMethods.ts | 4 +- src/neo/token-bridge/README.md | 4 +- src/neo/token-bridge/readOnlyMethods.ts | 4 +- src/neo/utils.ts | 14 +-- src/neo/wallet/README.md | 4 +- src/neo/wallet/walletOperations.ts | 6 +- 38 files changed, 252 insertions(+), 103 deletions(-) diff --git a/README.md b/README.md index cff36cd..e6d3b14 100644 --- a/README.md +++ b/README.md @@ -32,13 +32,14 @@ See `env-template` for all required and optional variables. ### Neo Chain Variables - `NEO_NODE_URL` - RPC URL of the Neo node -- `WALLET_PATH` - Path to your Neo wallet JSON file -- `WALLET_PASSWORD` - Password for the wallet (if encrypted) +- `NEO_WALLET_PATH` - Path to your Neo wallet JSON file +- `NEO_WALLET_PASSWORD` - Password for the wallet (if encrypted) - Contract-specific hashes (e.g., `MESSAGE_BRIDGE_CONTRACT_HASH`, `NATIVE_BRIDGE_CONTRACT_HASH`) ### EVM Chain Variables - `EVM_RPC_URL` - RPC URL of the EVM node (defaults to http://localhost:8545) -- `EVM_PRIVATE_KEY` - Private key for the wallet (required for write operations) +- `EVM_WALLET_PATH` - Path to your EVM wallet JSON file +- `EVM_WALLET_PASSWORD` - Password for the wallet (if encrypted) - Contract-specific addresses (e.g., `EVM_MESSAGE_BRIDGE_CONTRACT_ADDRESS`, `EVM_NATIVE_BRIDGE_CONTRACT_ADDRESS`) ### Operation-specific Variables diff --git a/env-template b/env-template index fd8ec67..19f1692 100644 --- a/env-template +++ b/env-template @@ -1,11 +1,21 @@ NEO_NODE_URL=http://localhost:40332 -#Conrtract hashes +# EVM Configuration +EVM_RPC_URL=http://localhost:8545 + +# Neo Contract hashes MESSAGE_BRIDGE_CONTRACT_HASH=bd98300a1951d72533fa749010265f71c4cfff38 BRIDGE_MANAGEMENT_CONTRACT_HASH=f0e6bccc463fa39fb21c4d0b69c2c279cd3d12d9 EXECUTION_MANAGER_CONTRACT_HASH=0xa4cda6c7b19c7e06ad702f1bc7e20ecc21e0a050 NATIVE_TOKEN_BRIDGE_CONTRACT_HASH=0x356376dcd5580f49f8b4d1274745ac55ad858784 +# EVM Contract addresses +EVM_MESSAGE_BRIDGE_CONTRACT_ADDRESS= +EVM_EXECUTION_MANAGER_CONTRACT_ADDRESS= +EVM_NATIVE_BRIDGE_CONTRACT_ADDRESS= +EVM_TOKEN_BRIDGE_CONTRACT_ADDRESS= +EVM_BRIDGE_MANAGEMENT_CONTRACT_ADDRESS= + # Validator public keys VALIDATOR_PUBLIC_KEY=0x02a0150e31043503248d2e3cb1e55011062d19a02a2da82f3cb55d9a1b967a601d NEW_VALIDATOR_PUBLIC_KEY=0x... # Fill with new validator pubkey when replacing validator @@ -80,7 +90,10 @@ NEW_MIN_TOKEN_DEPOSIT=... # New minimum token deposit NEW_MAX_TOKEN_DEPOSIT=... # New maximum token deposit NEW_MAX_TOKEN_WITHDRAWALS=... # New maximum token withdrawals -# pausing will only work if this is the governor account -# changing validator will only work if this is the owner account -WALLET_PATH=../neon3-funding/neon3-wallets/personal.json -WALLET_PASSWORD= +# Neo wallet configuration +NEO_WALLET_PATH=../neon3-funding/neon3-wallets/personal.json +NEO_WALLET_PASSWORD= + +# EVM wallet configuration +EVM_WALLET_PATH=../neox-funding/neox-wallets/personal.json +EVM_WALLET_PASSWORD= diff --git a/package-lock.json b/package-lock.json index 3d0c04a..1ff51e9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,6 +11,7 @@ "dependencies": { "@bane-labs/bridge-sdk-ts": "file:../../../bridge-sdk-ts/bane-labs-bridge-sdk-ts-1.0.0-beta.7.tgz", "dotenv": "^17.2.3", + "ethers": "^6.16.0", "viem": "^2.21.53" }, "devDependencies": { @@ -27,11 +28,11 @@ "node_modules/@bane-labs/bridge-sdk-ts": { "version": "1.0.0-beta.7", "resolved": "file:../../../bridge-sdk-ts/bane-labs-bridge-sdk-ts-1.0.0-beta.7.tgz", - "integrity": "sha512-w0YM24Ct+q6E+lc4HGSAobpYZDV3xqfKRC1EJdqif23FnSQMIqZq/kHR7UVWAJVWcHA+hLD/9S2LV9n9KW6t1g==", + "integrity": "sha512-M8Kvq0maUNcctUnUrIdkmLOehV1OkXx2jsTISd4cDDOJdTlvTKO0gu2VU6Wq09jYZfZg3x/QM3syVGICIBXxgw==", "license": "Apache-2.0", "dependencies": { "@cityofzion/neon-js": "5.8.0", - "@gitmyabi/bane-labs--bridge-evm-contracts": "^0.0.5", + "@gitmyabi/bane-labs--bridge-evm-contracts": "^0.0.6", "viem": "^2.45.0" } }, @@ -521,7 +522,7 @@ } }, "node_modules/@gitmyabi/bane-labs--bridge-evm-contracts": { - "version": "0.0.5", + "version": "0.0.6", "license": "MIT", "dependencies": { "viem": "^2.0.0" @@ -681,6 +682,12 @@ "node": ">=0.4.0" } }, + "node_modules/aes-js": { + "version": "4.0.0-beta.5", + "resolved": "https://registry.npmjs.org/aes-js/-/aes-js-4.0.0-beta.5.tgz", + "integrity": "sha512-G965FqalsNyrPqgEGON7nIx1e/OVENSgiEIzyC63haUMuvNnwIgIjMs52hlTCKhkBny7A2ORNlfY9Zu+jmGk1Q==", + "license": "MIT" + }, "node_modules/arg": { "version": "4.1.3", "dev": true, @@ -851,6 +858,100 @@ "npm": ">=9" } }, + "node_modules/ethers": { + "version": "6.16.0", + "resolved": "https://registry.npmjs.org/ethers/-/ethers-6.16.0.tgz", + "integrity": "sha512-U1wulmetNymijEhpSEQ7Ct/P/Jw9/e7R1j5XIbPRydgV2DjLVMsULDlNksq3RQnFgKoLlZf88ijYtWEXcPa07A==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/ethers-io/" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "dependencies": { + "@adraffy/ens-normalize": "1.10.1", + "@noble/curves": "1.2.0", + "@noble/hashes": "1.3.2", + "@types/node": "22.7.5", + "aes-js": "4.0.0-beta.5", + "tslib": "2.7.0", + "ws": "8.17.1" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/ethers/node_modules/@adraffy/ens-normalize": { + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/@adraffy/ens-normalize/-/ens-normalize-1.10.1.tgz", + "integrity": "sha512-96Z2IP3mYmF1Xg2cDm8f1gWGf/HUVedQ3FMifV4kG/PQ4yEP51xDtRAEfhVNt5f/uzpNkZHwWQuUcu6D6K+Ekw==", + "license": "MIT" + }, + "node_modules/ethers/node_modules/@noble/curves": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.2.0.tgz", + "integrity": "sha512-oYclrNgRaM9SsBUBVbb8M6DTV7ZHRTKugureoYEncY5c65HOmRzvSiTE3y5CYaPYJA/GVkrhXEoF0M3Ya9PMnw==", + "license": "MIT", + "dependencies": { + "@noble/hashes": "1.3.2" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/ethers/node_modules/@noble/hashes": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.2.tgz", + "integrity": "sha512-MVC8EAQp7MvEcm30KWENFjgR+Mkmf+D189XJTkFIlwohU5hcBbn1ZkKq7KVTi2Hme3PMGF390DaL52beVrIihQ==", + "license": "MIT", + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/ethers/node_modules/@types/node": { + "version": "22.7.5", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.7.5.tgz", + "integrity": "sha512-jML7s2NAzMWc//QSJ1a3prpk78cOPchGvXJsC3C6R6PSMoooztvRVQEz89gmBTBY1SPMaqo5teB4uNHPdetShQ==", + "license": "MIT", + "dependencies": { + "undici-types": "~6.19.2" + } + }, + "node_modules/ethers/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==", + "license": "MIT" + }, + "node_modules/ethers/node_modules/ws": { + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz", + "integrity": "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==", + "license": "MIT", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, "node_modules/eventemitter3": { "version": "5.0.1", "license": "MIT" @@ -1125,6 +1226,12 @@ } } }, + "node_modules/tslib": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", + "license": "0BSD" + }, "node_modules/tsx": { "version": "4.20.6", "dev": true, diff --git a/package.json b/package.json index 8e59f0e..6f49ec3 100644 --- a/package.json +++ b/package.json @@ -99,6 +99,7 @@ "dependencies": { "@bane-labs/bridge-sdk-ts": "file:../../../bridge-sdk-ts/bane-labs-bridge-sdk-ts-1.0.0-beta.7.tgz", "dotenv": "^17.2.3", + "ethers": "^6.16.0", "viem": "^2.21.53" }, "devDependencies": { diff --git a/src/evm/README.md b/src/evm/README.md index 6a79de1..1670b5c 100644 --- a/src/evm/README.md +++ b/src/evm/README.md @@ -27,7 +27,8 @@ Create a `.env` file in the project root with the following variables: ```env # EVM Network Configuration EVM_RPC_URL=http://localhost:8545 -EVM_PRIVATE_KEY=0x... +EVM_WALLET_PATH=../neox-funding/neox-wallets/personal.json +EVM_WALLET_PASSWORD= # Contract Addresses EVM_MESSAGE_BRIDGE_CONTRACT_ADDRESS=0x... @@ -71,7 +72,7 @@ See individual README files in each subdirectory for more specific examples and Read-only operations only require `EVM_RPC_URL` and contract addresses. They use the `read` property of contract instances. ### Write Operations -Write operations require `EVM_PRIVATE_KEY` in addition to read requirements. They use the `write` property and return transaction hashes. +Write operations require `EVM_WALLET_PATH` and `EVM_WALLET_PASSWORD` in addition to read requirements. They use the `write` property and return transaction hashes. ## Error Handling diff --git a/src/evm/bridge-management/README.md b/src/evm/bridge-management/README.md index 13ca104..f3f6e42 100644 --- a/src/evm/bridge-management/README.md +++ b/src/evm/bridge-management/README.md @@ -25,7 +25,8 @@ This directory contains examples for interacting with the EVM Bridge Management - `EVM_BRIDGE_MANAGEMENT_CONTRACT_ADDRESS` - Contract address of the EVM Bridge Management - `EVM_RPC_URL` - RPC URL of the EVM node (defaults to http://localhost:8545) -- `EVM_PRIVATE_KEY` - Private key for the wallet (required for write operations) +- `EVM_WALLET_PATH` - Path to the EVM wallet file +- `EVM_WALLET_PASSWORD` - Password for the wallet (if encrypted) ### Operation-specific Variables - For `ownerRelayerGovernor.ts`: `MANAGEMENT_ACTION` (set-owner, set-relayer, set-governor, set-security-guard), corresponding `NEW_OWNER`, `NEW_RELAYER`, `NEW_GOVERNOR`, `NEW_SECURITY_GUARD` diff --git a/src/evm/bridge-management/ownerRelayerGovernor.ts b/src/evm/bridge-management/ownerRelayerGovernor.ts index 14660b2..87abc1a 100644 --- a/src/evm/bridge-management/ownerRelayerGovernor.ts +++ b/src/evm/bridge-management/ownerRelayerGovernor.ts @@ -3,7 +3,7 @@ import { createBridgeManagementFromEnvironment, ensureEnv } from "../utils"; async function main() { const action = process.env.MANAGEMENT_ACTION; - const bridgeManagement = createBridgeManagementFromEnvironment(); + const bridgeManagement = await createBridgeManagementFromEnvironment(); switch (action) { case 'transfer-ownership': { diff --git a/src/evm/bridge-management/readOnlyMethods.ts b/src/evm/bridge-management/readOnlyMethods.ts index 7478cb6..a985250 100644 --- a/src/evm/bridge-management/readOnlyMethods.ts +++ b/src/evm/bridge-management/readOnlyMethods.ts @@ -44,7 +44,7 @@ async function main() { const { createBridgeManagementFromEnvironment } = await import("../utils"); try { - const bridgeManagement = createBridgeManagementFromEnvironment(); + const bridgeManagement = await createBridgeManagementFromEnvironment(); await callReadOnlyMethods(bridgeManagement); } catch (error) { console.error("Failed to test EVM Bridge Management read-only methods:", error); diff --git a/src/evm/bridge-management/validatorManagement.ts b/src/evm/bridge-management/validatorManagement.ts index d52086e..2850058 100644 --- a/src/evm/bridge-management/validatorManagement.ts +++ b/src/evm/bridge-management/validatorManagement.ts @@ -3,7 +3,7 @@ import { createBridgeManagementFromEnvironment, ensureEnv } from "../utils"; async function main() { const action = process.env.VALIDATOR_ACTION; - const bridgeManagement = createBridgeManagementFromEnvironment(); + const bridgeManagement = await createBridgeManagementFromEnvironment(); switch (action) { case 'add': { diff --git a/src/evm/execution-manager/README.md b/src/evm/execution-manager/README.md index 0221999..2f214d5 100644 --- a/src/evm/execution-manager/README.md +++ b/src/evm/execution-manager/README.md @@ -17,7 +17,8 @@ This directory contains examples for interacting with the EVM ExecutionManager c - `EVM_EXECUTION_MANAGER_CONTRACT_ADDRESS` - Contract address of the EVM ExecutionManager - `EVM_RPC_URL` - RPC URL of the EVM node (defaults to http://localhost:8545) -- `EVM_PRIVATE_KEY` - Private key for the wallet (required for write operations) +- `EVM_WALLET_PATH` - Path to the EVM wallet file +- `EVM_WALLET_PASSWORD` - Password for the wallet (if encrypted) ### Operation-specific Variables - For `executeMessage.ts`: diff --git a/src/evm/execution-manager/executeMessage.ts b/src/evm/execution-manager/executeMessage.ts index 54d57a1..e580f1d 100644 --- a/src/evm/execution-manager/executeMessage.ts +++ b/src/evm/execution-manager/executeMessage.ts @@ -25,10 +25,10 @@ async function main() { ensureEnv(); try { - const executionManager = createExecutionManagerFromEnvironment(); + const executionManager = await createExecutionManagerFromEnvironment(); - if (!process.env.EVM_PRIVATE_KEY) { - throw new Error('Wallet client is required for write operations. Please set EVM_PRIVATE_KEY environment variable.'); + if (!process.env.EVM_WALLET_PATH) { + throw new Error('Wallet client is required for write operations. Please set EVM_WALLET_PATH environment variable.'); } const nonceStr = requireEnvVar('MESSAGE_NONCE'); diff --git a/src/evm/execution-manager/readOnlyMethods.ts b/src/evm/execution-manager/readOnlyMethods.ts index d84a136..626f12e 100644 --- a/src/evm/execution-manager/readOnlyMethods.ts +++ b/src/evm/execution-manager/readOnlyMethods.ts @@ -30,7 +30,7 @@ async function main() { const { createExecutionManagerFromEnvironment } = await import("../utils"); try { - const executionManager = createExecutionManagerFromEnvironment(); + const executionManager = await createExecutionManagerFromEnvironment(); await callReadOnlyMethods(executionManager); } catch (error) { console.error("Failed to test EVM Execution Manager read-only methods:", error); diff --git a/src/evm/message-bridge/README.md b/src/evm/message-bridge/README.md index 8445e55..f90228d 100644 --- a/src/evm/message-bridge/README.md +++ b/src/evm/message-bridge/README.md @@ -27,7 +27,8 @@ This directory contains examples for interacting with the EVM Message Bridge con - `EVM_MESSAGE_BRIDGE_CONTRACT_ADDRESS` - Contract address of the EVM Message Bridge - `EVM_RPC_URL` - RPC URL of the EVM node (defaults to http://localhost:8545) -- `EVM_PRIVATE_KEY` - Private key for the wallet (required for write operations) +- `EVM_WALLET_PATH` - Path to the EVM wallet file +- `EVM_WALLET_PASSWORD` - Password for the wallet (if encrypted) ### Operation-specific Variables - For `sendMessage.ts`: `MESSAGE_BRIDGE_OPERATION` (send-executable, send-result, send-store-only), `MESSAGE_EXECUTABLE_DATA`, `MESSAGE_STORE_RESULT` (boolean), `MESSAGE_NONCE` (for result), `MESSAGE_STORE_ONLY_DATA` diff --git a/src/evm/message-bridge/encodeExecutableMessage.ts b/src/evm/message-bridge/encodeExecutableMessage.ts index f2a719b..cb4047e 100644 --- a/src/evm/message-bridge/encodeExecutableMessage.ts +++ b/src/evm/message-bridge/encodeExecutableMessage.ts @@ -40,7 +40,7 @@ async function encodeExecutableMessageExamples() { console.log("\n--- Testing Message Bridge State ---"); // Test current message bridge state using actual available methods - const messageBridge = createMessageBridgeFromEnvironment(); + const messageBridge = await createMessageBridgeFromEnvironment(); const evmToNeoState = await messageBridge.evmToNeoState(); console.log(`Current EVM to Neo state: nonce=${evmToNeoState.nonce}, root=${evmToNeoState.root}`); diff --git a/src/evm/message-bridge/executeMessage.ts b/src/evm/message-bridge/executeMessage.ts index 7beec17..bfcca24 100644 --- a/src/evm/message-bridge/executeMessage.ts +++ b/src/evm/message-bridge/executeMessage.ts @@ -32,10 +32,10 @@ async function main() { ensureEnv(); try { - const messageBridge = createMessageBridgeFromEnvironment(); + const messageBridge = await createMessageBridgeFromEnvironment(); - if (!process.env.EVM_PRIVATE_KEY) { - throw new Error('Wallet client is required for write operations. Please set EVM_PRIVATE_KEY environment variable.'); + if (!process.env.EVM_WALLET_PATH) { + throw new Error('Wallet client is required for write operations. Please set EVM_WALLET_PATH environment variable.'); } const nonceStr = requireEnvVar('MESSAGE_NONCE'); diff --git a/src/evm/message-bridge/pauseOperations.ts b/src/evm/message-bridge/pauseOperations.ts index 0488af3..3b6f413 100644 --- a/src/evm/message-bridge/pauseOperations.ts +++ b/src/evm/message-bridge/pauseOperations.ts @@ -63,10 +63,10 @@ async function main() { ensureEnv(); try { - const messageBridge = createMessageBridgeFromEnvironment(); + const messageBridge = await createMessageBridgeFromEnvironment(); - if (!process.env.EVM_PRIVATE_KEY) { - throw new Error('Wallet client is required for write operations. Please set EVM_PRIVATE_KEY environment variable.'); + if (!process.env.EVM_WALLET_PATH) { + throw new Error('Wallet client is required for write operations. Please set EVM_WALLET_PATH environment variable.'); } await testPauseOperations(messageBridge); diff --git a/src/evm/message-bridge/readOnlyMethods.ts b/src/evm/message-bridge/readOnlyMethods.ts index df5795c..62304fa 100644 --- a/src/evm/message-bridge/readOnlyMethods.ts +++ b/src/evm/message-bridge/readOnlyMethods.ts @@ -57,7 +57,7 @@ async function main() { const { createMessageBridgeFromEnvironment } = await import("../utils"); try { - const messageBridge = createMessageBridgeFromEnvironment(); + const messageBridge = await createMessageBridgeFromEnvironment(); await callReadOnlyMethods(messageBridge); } catch (error) { console.error("Failed to test EVM Message Bridge read-only methods:", error); diff --git a/src/evm/message-bridge/sendMessage.ts b/src/evm/message-bridge/sendMessage.ts index a2a4ac5..b2fea16 100644 --- a/src/evm/message-bridge/sendMessage.ts +++ b/src/evm/message-bridge/sendMessage.ts @@ -13,9 +13,7 @@ async function sendExecutableMessage(messageBridge: EvmMessageBridge) { const hash = await messageBridge.sendExecutableMessage( messageData as `0x${string}`, storeResult, - // { - // value: sendingFee - // } + { value: sendingFee } ); console.log('Executable message sent successfully. Transaction hash:', hash); @@ -32,9 +30,9 @@ async function sendResultMessage(messageBridge: EvmMessageBridge) { console.log(`Sending fee: ${sendingFee} wei`); const hash = await messageBridge.sendResultMessage(nonce, - // { - // value: sendingFee - // } + { + value: sendingFee + } ); console.log('Result message sent successfully. Transaction hash:', hash); @@ -50,9 +48,9 @@ async function sendStoreOnlyMessage(messageBridge: EvmMessageBridge) { console.log(`Sending fee: ${sendingFee} wei`); const hash = await messageBridge.sendStoreOnlyMessage(messageData as `0x${string}`, - // { - // value: sendingFee - // } + { + value: sendingFee + } ); console.log('Store-only message sent successfully. Transaction hash:', hash); @@ -63,10 +61,10 @@ async function main() { ensureEnv(); try { - const messageBridge = createMessageBridgeFromEnvironment(); + const messageBridge = await createMessageBridgeFromEnvironment(); - if (!process.env.EVM_PRIVATE_KEY) { - throw new Error('Wallet client is required for write operations. Please set EVM_PRIVATE_KEY environment variable.'); + if (!process.env.EVM_WALLET_PATH) { + throw new Error('Wallet client is required for write operations. Please set EVM_WALLET_PATH environment variable.'); } const operation = process.env.MESSAGE_BRIDGE_OPERATION; diff --git a/src/evm/message-bridge/setExecutionManager.ts b/src/evm/message-bridge/setExecutionManager.ts index 82d662a..1267b80 100644 --- a/src/evm/message-bridge/setExecutionManager.ts +++ b/src/evm/message-bridge/setExecutionManager.ts @@ -28,10 +28,10 @@ async function main() { ensureEnv(); try { - const messageBridge = createMessageBridgeFromEnvironment(); + const messageBridge = await createMessageBridgeFromEnvironment(); - if (!process.env.EVM_PRIVATE_KEY) { - throw new Error('Wallet client is required for write operations. Please set EVM_PRIVATE_KEY environment variable.'); + if (!process.env.EVM_WALLET_PATH) { + throw new Error('Wallet client is required for write operations. Please set EVM_WALLET_PATH environment variable.'); } const executionManagerAddress = requireEnvVar('EXECUTION_MANAGER_ADDRESS'); diff --git a/src/evm/native-bridge/README.md b/src/evm/native-bridge/README.md index c46b108..95320c3 100644 --- a/src/evm/native-bridge/README.md +++ b/src/evm/native-bridge/README.md @@ -30,7 +30,8 @@ This directory contains examples for interacting with the EVM Native Bridge cont - `EVM_NATIVE_BRIDGE_CONTRACT_ADDRESS` - Contract address of the EVM Native Bridge - `EVM_RPC_URL` - RPC URL of the EVM node (defaults to http://localhost:8545) -- `EVM_PRIVATE_KEY` - Private key for the wallet (required for write operations) +- `EVM_WALLET_PATH` - Path to the EVM wallet file +- `EVM_WALLET_PASSWORD` - Password for the wallet (if encrypted) ### Optional Environment Variables for Testing - `NATIVE_CLAIM_NONCE` - Nonce to check for claimable native tokens (defaults to 1) diff --git a/src/evm/native-bridge/nativeBridgeOperations.ts b/src/evm/native-bridge/nativeBridgeOperations.ts index c60cc1b..46e4286 100644 --- a/src/evm/native-bridge/nativeBridgeOperations.ts +++ b/src/evm/native-bridge/nativeBridgeOperations.ts @@ -8,7 +8,7 @@ async function nativeBridgeOperations() { return; } - const nativeBridge = createNativeBridgeFromEnvironment(); + const nativeBridge = await createNativeBridgeFromEnvironment(); try { switch (operation) { diff --git a/src/evm/native-bridge/pauseOperations.ts b/src/evm/native-bridge/pauseOperations.ts index c7af6ba..94d6884 100644 --- a/src/evm/native-bridge/pauseOperations.ts +++ b/src/evm/native-bridge/pauseOperations.ts @@ -3,7 +3,7 @@ import { createNativeBridgeFromEnvironment, ensureEnv } from "../utils"; async function performPauseOperations() { console.log("\n--- Testing EVM Native Bridge Pause/Unpause Operations ---"); - const nativeBridge = createNativeBridgeFromEnvironment(); + const nativeBridge = await createNativeBridgeFromEnvironment(); try { console.log("\n1. Initial State Check:"); diff --git a/src/evm/native-bridge/readOnlyMethods.ts b/src/evm/native-bridge/readOnlyMethods.ts index b7b267c..e4b1382 100644 --- a/src/evm/native-bridge/readOnlyMethods.ts +++ b/src/evm/native-bridge/readOnlyMethods.ts @@ -70,7 +70,7 @@ async function main() { const { createNativeBridgeFromEnvironment } = await import("../utils"); try { - const nativeBridge = createNativeBridgeFromEnvironment(); + const nativeBridge = await createNativeBridgeFromEnvironment(); await callReadOnlyMethods(nativeBridge); } catch (error) { console.error("Failed to test EVM Native Bridge read-only methods:", error); diff --git a/src/evm/token-bridge/README.md b/src/evm/token-bridge/README.md index 54d7478..ddb1cf2 100644 --- a/src/evm/token-bridge/README.md +++ b/src/evm/token-bridge/README.md @@ -28,7 +28,8 @@ This directory contains examples for interacting with the EVM Token Bridge contr - `EVM_TOKEN_BRIDGE_CONTRACT_ADDRESS` - Contract address of the EVM Token Bridge - `EVM_RPC_URL` - RPC URL of the EVM node (defaults to http://localhost:8545) -- `EVM_PRIVATE_KEY` - Private key for the wallet (required for write operations) +- `EVM_WALLET_PATH` - Path to the EVM wallet file +- `EVM_WALLET_PASSWORD` - Password for the wallet (if encrypted) ### Optional Environment Variables for Testing - `TOKEN_ADDRESS` - Specific EVM token address to query detailed information for diff --git a/src/evm/token-bridge/readOnlyMethods.ts b/src/evm/token-bridge/readOnlyMethods.ts index d2ab05c..40f819d 100644 --- a/src/evm/token-bridge/readOnlyMethods.ts +++ b/src/evm/token-bridge/readOnlyMethods.ts @@ -121,7 +121,7 @@ async function main() { const { createTokenBridgeFromEnvironment } = await import("../utils"); try { - const tokenBridge = createTokenBridgeFromEnvironment(); + const tokenBridge = await createTokenBridgeFromEnvironment(); await callReadOnlyMethods(tokenBridge); } catch (error) { console.error("Failed to test EVM Token Bridge read-only methods:", error); diff --git a/src/evm/token-bridge/tokenBridgeOperations.ts b/src/evm/token-bridge/tokenBridgeOperations.ts index 74be5c8..1a4cc12 100644 --- a/src/evm/token-bridge/tokenBridgeOperations.ts +++ b/src/evm/token-bridge/tokenBridgeOperations.ts @@ -10,7 +10,7 @@ async function tokenBridgeOperations() { return; } - const tokenBridge = createTokenBridgeFromEnvironment(); + const tokenBridge = await createTokenBridgeFromEnvironment(); try { switch (operation) { diff --git a/src/evm/utils.ts b/src/evm/utils.ts index 0584e81..d46e6ae 100644 --- a/src/evm/utils.ts +++ b/src/evm/utils.ts @@ -7,18 +7,33 @@ import { EvmBridgeManagement, EvmMessageBridgeFactory, EvmNativeBridgeFactory, EvmTokenBridgeFactory, EvmExecutionManagerFactory, EvmBridgeManagementFactory } from "@bane-labs/bridge-sdk-ts"; -import { createPublicClient, createWalletClient, http, type Address } from 'viem'; -import { privateKeyToAccount } from 'viem/accounts'; +import { createPublicClient, createWalletClient, http, type Address, PrivateKeyAccount } from 'viem'; +import { privateKeyToAccount, HDAccount } from 'viem/accounts'; import { mainnet } from 'viem/chains'; +import * as fs from 'fs'; import dotenv from "dotenv"; export function ensureEnv() { dotenv.config(); } -export function createEvmContractWrapperConfig(contractAddress: Address): EvmContractWrapperConfig { - const rpcUrl = process.env.EVM_RPC_URL || 'http://localhost:8545'; - const privateKey = process.env.EVM_PRIVATE_KEY; +async function createAccountFromWalletFile(walletPath: string, password: string): Promise { + if (!fs.existsSync(walletPath)) { + throw new Error(`Wallet file not found: ${walletPath}`); + } + + const walletJson = fs.readFileSync(walletPath, 'utf8'); + + // Use ethers for decryption since viem doesn't have native support for encrypted JSON wallets yet + const { ethers } = await import('ethers'); + const wallet = await ethers.Wallet.fromEncryptedJson(walletJson, password); + + // Convert to viem account + return privateKeyToAccount(wallet.privateKey as `0x${string}`); +} + +export async function createEvmContractWrapperConfig(contractAddress: Address): Promise { + const rpcUrl = process.env.EVM_RPC_URL || 'http://localhost:8562'; const publicClient = createPublicClient({ chain: mainnet, @@ -26,13 +41,21 @@ export function createEvmContractWrapperConfig(contractAddress: Address): EvmCon }); let walletClient = undefined; - if (privateKey) { - const account = privateKeyToAccount(privateKey as `0x${string}`); - walletClient = createWalletClient({ - account, - chain: mainnet, - transport: http(rpcUrl) - }); + + const walletPath = process.env.EVM_WALLET_PATH; + const walletPassword = process.env.EVM_WALLET_PASSWORD || ''; + + if (walletPath) { + try { + const account = await createAccountFromWalletFile(walletPath, walletPassword); + walletClient = createWalletClient({ + account, + chain: mainnet, + transport: http(rpcUrl) + }); + } catch (error) { + throw new Error(`Failed to load EVM wallet from ${walletPath}: ${error instanceof Error ? error.message : error}`); + } } return { @@ -42,53 +65,53 @@ export function createEvmContractWrapperConfig(contractAddress: Address): EvmCon }; } -export function createMessageBridgeFromEnvironment(): EvmMessageBridge { +export async function createMessageBridgeFromEnvironment(): Promise { const contractAddress = process.env.EVM_MESSAGE_BRIDGE_CONTRACT_ADDRESS; if (!contractAddress) { throw new Error('EVM_MESSAGE_BRIDGE_CONTRACT_ADDRESS environment variable is required'); } - const config = createEvmContractWrapperConfig(contractAddress as Address); + const config = await createEvmContractWrapperConfig(contractAddress as Address); return EvmMessageBridgeFactory.create(config); } -export function createExecutionManagerFromEnvironment(): EvmExecutionManager { +export async function createExecutionManagerFromEnvironment(): Promise { const contractAddress = process.env.EVM_EXECUTION_MANAGER_CONTRACT_ADDRESS; if (!contractAddress) { throw new Error('EVM_EXECUTION_MANAGER_CONTRACT_ADDRESS environment variable is required'); } - const config = createEvmContractWrapperConfig(contractAddress as Address); + const config = await createEvmContractWrapperConfig(contractAddress as Address); return EvmExecutionManagerFactory.create(config); } -export function createNativeBridgeFromEnvironment(): EvmNativeBridge { +export async function createNativeBridgeFromEnvironment(): Promise { const contractAddress = process.env.EVM_NATIVE_BRIDGE_CONTRACT_ADDRESS; if (!contractAddress) { throw new Error('EVM_NATIVE_BRIDGE_CONTRACT_ADDRESS environment variable is required'); } - const config = createEvmContractWrapperConfig(contractAddress as Address); + const config = await createEvmContractWrapperConfig(contractAddress as Address); return EvmNativeBridgeFactory.create(config); } -export function createTokenBridgeFromEnvironment(): EvmTokenBridge { +export async function createTokenBridgeFromEnvironment(): Promise { const contractAddress = process.env.EVM_TOKEN_BRIDGE_CONTRACT_ADDRESS; if (!contractAddress) { throw new Error('EVM_TOKEN_BRIDGE_CONTRACT_ADDRESS environment variable is required'); } - const config = createEvmContractWrapperConfig(contractAddress as Address); + const config = await createEvmContractWrapperConfig(contractAddress as Address); return EvmTokenBridgeFactory.create(config); } -export function createBridgeManagementFromEnvironment(): EvmBridgeManagement { +export async function createBridgeManagementFromEnvironment(): Promise { const contractAddress = process.env.EVM_BRIDGE_MANAGEMENT_CONTRACT_ADDRESS; if (!contractAddress) { throw new Error('EVM_BRIDGE_MANAGEMENT_CONTRACT_ADDRESS environment variable is required'); } - const config = createEvmContractWrapperConfig(contractAddress as Address); + const config = await createEvmContractWrapperConfig(contractAddress as Address); return EvmBridgeManagementFactory.create(config); } diff --git a/src/neo/execution-manager/README.md b/src/neo/execution-manager/README.md index b642a59..5c7e2e3 100644 --- a/src/neo/execution-manager/README.md +++ b/src/neo/execution-manager/README.md @@ -22,8 +22,8 @@ This directory contains examples for interacting with the ExecutionManager contr - `EXECUTION_MANAGER_CONTRACT_HASH` - Contract hash of the ExecutionManager - `NEO_NODE_URL` - RPC URL of the Neo node -- `WALLET_PATH` - Path to the wallet file -- `WALLET_PASSWORD` - Password for the wallet (if encrypted) +- `NEO_WALLET_PATH` - Path to the wallet file +- `NEO_WALLET_PASSWORD` - Password for the wallet (if encrypted) ### Operation-specific Variables - For `executeMessage.ts`: `MESSAGE_NONCE` (integer), `EXECUTABLE_CODE` diff --git a/src/neo/execution-manager/readOnlyMethods.ts b/src/neo/execution-manager/readOnlyMethods.ts index 202a531..aefc027 100644 --- a/src/neo/execution-manager/readOnlyMethods.ts +++ b/src/neo/execution-manager/readOnlyMethods.ts @@ -6,8 +6,8 @@ * Required environment variables: * - EXECUTION_MANAGER_CONTRACT_HASH: The contract hash of the ExecutionManager * - NEO_NODE_URL: The RPC URL of the Neo node - * - WALLET_PATH: Path to the wallet file - * - WALLET_PASSWORD: Password for the wallet (if encrypted) + * - NEO_WALLET_PATH: Path to the wallet file + * - NEO_WALLET_PASSWORD: Password for the wallet (if encrypted) * * Optional environment variables: * - MESSAGE_BRIDGE_CONTRACT_HASH: Used for testing serialization methods diff --git a/src/neo/management/README.md b/src/neo/management/README.md index e605bae..7ee01fa 100644 --- a/src/neo/management/README.md +++ b/src/neo/management/README.md @@ -27,8 +27,8 @@ This directory contains examples for interacting with the Management contract, w - `MANAGEMENT_CONTRACT_HASH` - Contract hash of the Management contract - `NEO_NODE_URL` - RPC URL of the Neo node -- `WALLET_PATH` - Path to the wallet file -- `WALLET_PASSWORD` - Password for the wallet (if encrypted) +- `NEO_WALLET_PATH` - Path to the wallet file +- `NEO_WALLET_PASSWORD` - Password for the wallet (if encrypted) ### Operation-specific Variables - For `ownerRelayerGovernor.ts`: `MANAGEMENT_ACTION` (set-owner, set-relayer, set-governor, set-security-guard), corresponding `NEW_OWNER`, `NEW_RELAYER`, `NEW_GOVERNOR`, `NEW_SECURITY_GUARD` diff --git a/src/neo/message-bridge/README.md b/src/neo/message-bridge/README.md index 0344509..2ea2c2b 100644 --- a/src/neo/message-bridge/README.md +++ b/src/neo/message-bridge/README.md @@ -29,8 +29,8 @@ This directory contains examples for interacting with the Message Bridge contrac - `MESSAGE_BRIDGE_CONTRACT_HASH` - Contract hash of the Message Bridge - `NEO_NODE_URL` - RPC URL of the Neo node -- `WALLET_PATH` - Path to the wallet file -- `WALLET_PASSWORD` - Password for the wallet (if encrypted) +- `NEO_WALLET_PATH` - Path to the wallet file +- `NEO_WALLET_PASSWORD` - Password for the wallet (if encrypted) ### Operation-specific Variables - For `sendMessage.ts`: `MESSAGE_BRIDGE_OPERATION` (send-executable, send-result, send-store-only), `MESSAGE_EXECUTABLE_DATA`, `MESSAGE_STORE_RESULT` (boolean), `MESSAGE_NONCE` (for result), `MESSAGE_STORE_ONLY_DATA` diff --git a/src/neo/native-bridge/README.md b/src/neo/native-bridge/README.md index 151d336..ea576a3 100644 --- a/src/neo/native-bridge/README.md +++ b/src/neo/native-bridge/README.md @@ -30,8 +30,8 @@ This directory contains examples for interacting with the Native Bridge contract - `NATIVE_BRIDGE_CONTRACT_HASH` - Contract hash of the Native Bridge - `NEO_NODE_URL` - RPC URL of the Neo node -- `WALLET_PATH` - Path to the wallet file -- `WALLET_PASSWORD` - Password for the wallet (if encrypted) +- `NEO_WALLET_PATH` - Path to the wallet file +- `NEO_WALLET_PASSWORD` - Password for the wallet (if encrypted) ### Operation-specific Variables See individual files for specific environment variables required for each operation. diff --git a/src/neo/native-bridge/readOnlyMethods.ts b/src/neo/native-bridge/readOnlyMethods.ts index 54b82b5..1e194b2 100644 --- a/src/neo/native-bridge/readOnlyMethods.ts +++ b/src/neo/native-bridge/readOnlyMethods.ts @@ -6,8 +6,8 @@ * Required environment variables: * - NATIVE_BRIDGE_CONTRACT_HASH: The contract hash of the Native Bridge * - NEO_NODE_URL: The RPC URL of the Neo node - * - WALLET_PATH: Path to the wallet file - * - WALLET_PASSWORD: Password for the wallet (if encrypted) + * - NEO_WALLET_PATH: Path to the wallet file + * - NEO_WALLET_PASSWORD: Password for the wallet (if encrypted) * * Usage: * npm run nb:readonly diff --git a/src/neo/token-bridge/README.md b/src/neo/token-bridge/README.md index 775da6d..9824937 100644 --- a/src/neo/token-bridge/README.md +++ b/src/neo/token-bridge/README.md @@ -28,8 +28,8 @@ This directory contains examples for interacting with the Token Bridge contract, - `TOKEN_BRIDGE_CONTRACT_HASH` - Contract hash of the Token Bridge - `NEO_NODE_URL` - RPC URL of the Neo node -- `WALLET_PATH` - Path to the wallet file -- `WALLET_PASSWORD` - Password for the wallet (if encrypted) +- `NEO_WALLET_PATH` - Path to the wallet file +- `NEO_WALLET_PASSWORD` - Password for the wallet (if encrypted) ### Operation-specific Variables See individual files for specific environment variables required for each operation. diff --git a/src/neo/token-bridge/readOnlyMethods.ts b/src/neo/token-bridge/readOnlyMethods.ts index 83bfe73..4fb6b29 100644 --- a/src/neo/token-bridge/readOnlyMethods.ts +++ b/src/neo/token-bridge/readOnlyMethods.ts @@ -6,8 +6,8 @@ * Required environment variables: * - TOKEN_BRIDGE_CONTRACT_HASH: The contract hash of the Token Bridge * - NEO_NODE_URL: The RPC URL of the Neo node - * - WALLET_PATH: Path to the wallet file - * - WALLET_PASSWORD: Password for the wallet (if encrypted) + * - NEO_WALLET_PATH: Path to the wallet file + * - NEO_WALLET_PASSWORD: Password for the wallet (if encrypted) * * Usage: * npm run tb:readonly diff --git a/src/neo/utils.ts b/src/neo/utils.ts index 88aef0e..b073e1b 100644 --- a/src/neo/utils.ts +++ b/src/neo/utils.ts @@ -70,8 +70,8 @@ export async function createNativeTokenBridgeFromEnvironment(): Promise { const contractHash = process.env.BRIDGE_MANAGEMENT_CONTRACT_HASH; const rpcUrl = process.env.NEO_NODE_URL; - const walletPath = process.env.WALLET_PATH; - const walletPassword = process.env.WALLET_PASSWORD || ''; + const walletPath = process.env.NEO_WALLET_PATH; + const walletPassword = process.env.NEO_WALLET_PASSWORD || ''; if (!contractHash) { throw new NeoGenericError('BRIDGE_MANAGEMENT_CONTRACT_HASH environment variable is required', 'MISSING_CONTRACT_HASH'); @@ -80,7 +80,7 @@ export async function createManagementFromEnvironment(): Promise { } async function createContractWrapperConfigFromEnv(contractHash: string) { - const walletPath = process.env.WALLET_PATH; + const walletPath = process.env.NEO_WALLET_PATH; if (!walletPath) { - throw new NeoGenericError('WALLET_PATH environment variable is required', 'MISSING_WALLET_PATH'); + throw new NeoGenericError('NEO_WALLET_PATH environment variable is required', 'MISSING_WALLET_PATH'); } - const walletPassword = process.env.WALLET_PASSWORD || ''; + const walletPassword = process.env.NEO_WALLET_PASSWORD || ''; const rpcUrl = process.env.NEO_NODE_URL; let account: Account | null; @@ -113,7 +113,7 @@ async function createContractWrapperConfigFromEnv(contractHash: string) { if (account && (account.tryGet("encrypted") || account.tryGet("WIF"))) { throw new NeoGenericError( - 'Wallet contains encrypted private key but no WALLET_PASSWORD environment variable provided. Please set WALLET_PASSWORD to decrypt the wallet.', + 'Wallet contains encrypted private key but no NEO_WALLET_PASSWORD environment variable provided. Please set NEO_WALLET_PASSWORD to decrypt the wallet.', 'ENCRYPTED_WALLET_NO_PASSWORD' ); } diff --git a/src/neo/wallet/README.md b/src/neo/wallet/README.md index 1967531..ab09a7b 100644 --- a/src/neo/wallet/README.md +++ b/src/neo/wallet/README.md @@ -13,8 +13,8 @@ This directory contains examples for interacting with Neo wallets, including loa ## Required Environment Variables -- `WALLET_PATH` - Path to the Neo wallet file -- `WALLET_PASSWORD` - Password for the wallet (if encrypted) +- `NEO_WALLET_PATH` - Path to the Neo wallet file +- `NEO_WALLET_PASSWORD` - Password for the wallet (if encrypted) - `NEO_NODE_URL` - RPC URL of the Neo node ## Features diff --git a/src/neo/wallet/walletOperations.ts b/src/neo/wallet/walletOperations.ts index 1b2b76c..de7c346 100644 --- a/src/neo/wallet/walletOperations.ts +++ b/src/neo/wallet/walletOperations.ts @@ -125,12 +125,12 @@ async function checkAccountBalances(accountAddress: string, rpcUrl: string, acco export type { NeoAssetBalance, NeoBalanceResponse, BalanceCache, AccountInfo }; export async function testWalletOperations(): Promise { - const walletPath = process.env.WALLET_PATH; - const walletPassword = process.env.WALLET_PASSWORD; + const walletPath = process.env.NEO_WALLET_PATH; + const walletPassword = process.env.NEO_WALLET_PASSWORD; const rpcUrl = process.env.NEO_NODE_URL; if (!walletPath) { - console.error('ERROR: No WALLET_PATH environment variable set. Please set it to load a wallet.'); + console.error('ERROR: No NEO_WALLET_PATH environment variable set. Please set it to load a wallet.'); return; } if (!rpcUrl) { From ae1f82efb32985443fa38f14a7fcee12323cd064 Mon Sep 17 00:00:00 2001 From: Otniel Nicola Date: Mon, 2 Feb 2026 12:55:10 +0200 Subject: [PATCH 6/8] feat: Add call for the encoded executable message --- .../message-bridge/encodeExecutableMessage.ts | 57 +++++++++++++++---- 1 file changed, 47 insertions(+), 10 deletions(-) diff --git a/src/evm/message-bridge/encodeExecutableMessage.ts b/src/evm/message-bridge/encodeExecutableMessage.ts index cb4047e..28bb937 100644 --- a/src/evm/message-bridge/encodeExecutableMessage.ts +++ b/src/evm/message-bridge/encodeExecutableMessage.ts @@ -1,4 +1,4 @@ -import { createMessageBridgeFromEnvironment, ensureEnv } from "../utils"; +import { createMessageBridgeFromEnvironment, ensureEnv, createEvmContractWrapperConfig } from "../utils"; import { encodeFunctionData, encodeAbiParameters, isAddress } from 'viem'; async function encodeExecutableMessageExamples() { @@ -95,23 +95,60 @@ function encodeEvmCall(target: string, storeResult: boolean, value: bigint, call // Test the encoded function call async function callViewFunction(contractAddress: string, encodedCallData: string) { try { - // Note: This would require a viem public client - // For now, we'll log what would be called - console.log(`Would call contract ${contractAddress} with data: ${encodedCallData}`); - console.log("Note: To actually execute this call, you would need a viem public client"); - console.log("Example: const result = await publicClient.call({ to: contractAddress, data: encodedCallData });"); + console.log(`Calling contract ${contractAddress} with data: ${encodedCallData}`); + + // Create public client from utils + const config = await createEvmContractWrapperConfig(contractAddress as `0x${string}`); + const publicClient = config.publicClient; + + // Make the actual call + const result = await publicClient.call({ + to: contractAddress as `0x${string}`, + data: encodedCallData as `0x${string}` + }); + + console.log("View function call result:", result); + + // Try to decode the result as uint256 for balanceOf + if (result.data && result.data !== '0x') { + try { + const balance = BigInt(result.data); + console.log("Decoded balance:", balance.toString()); + } catch (decodeError) { + console.log("Could not decode result as uint256:", result.data); + } + } else { + console.log("No data returned from call"); + } + } catch (error) { - console.log("Could not test view function call:", error instanceof Error ? error.message : error); + console.log("View function call failed:", error instanceof Error ? error.message : error); } } // Check if address is a contract using viem async function isContract(address: string): Promise { try { - // Use viem's address validation + // First validate the address format const isValidAddress = isAddress(address); - console.log(`Address validation: ${isValidAddress}`); - return isValidAddress; + if (!isValidAddress) { + console.log(`Invalid address format: ${address}`); + return false; + } + + // Create public client to check if address has code + const config = await createEvmContractWrapperConfig(address as `0x${string}`); + const publicClient = config.publicClient; + + const code = await publicClient.getBytecode({ + address: address as `0x${string}` + }); + + const hasCode = !!(code && code !== '0x' && code.length > 2); + console.log(`Address ${address} has bytecode: ${hasCode}`); + console.log(`Bytecode length: ${code ? code.length : 0} characters`); + + return hasCode; } catch (error) { console.log("Could not verify contract:", error instanceof Error ? error.message : error); return false; From c3de8a2fc31a342b017783283dec7ed40d041138 Mon Sep 17 00:00:00 2001 From: Otniel Nicola Date: Mon, 2 Feb 2026 13:22:12 +0200 Subject: [PATCH 7/8] fix: Use stringToHex to send store-only message --- env-template | 2 +- src/evm/message-bridge/sendMessage.ts | 10 ++++------ 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/env-template b/env-template index 19f1692..e23a1db 100644 --- a/env-template +++ b/env-template @@ -1,7 +1,7 @@ NEO_NODE_URL=http://localhost:40332 # EVM Configuration -EVM_RPC_URL=http://localhost:8545 +EVM_RPC_URL=http://localhost:8562 # Neo Contract hashes MESSAGE_BRIDGE_CONTRACT_HASH=bd98300a1951d72533fa749010265f71c4cfff38 diff --git a/src/evm/message-bridge/sendMessage.ts b/src/evm/message-bridge/sendMessage.ts index b2fea16..25f666b 100644 --- a/src/evm/message-bridge/sendMessage.ts +++ b/src/evm/message-bridge/sendMessage.ts @@ -1,4 +1,5 @@ import { EvmMessageBridge } from "@bane-labs/bridge-sdk-ts"; +import { stringToHex } from "viem"; import { createMessageBridgeFromEnvironment, ensureEnv, requireEnvVar } from "../utils"; async function sendExecutableMessage(messageBridge: EvmMessageBridge) { @@ -41,16 +42,13 @@ async function sendResultMessage(messageBridge: EvmMessageBridge) { async function sendStoreOnlyMessage(messageBridge: EvmMessageBridge) { const messageData = requireEnvVar('MESSAGE_STORE_ONLY_DATA'); - - console.log(`Sending store-only message with data: ${messageData}`); + const hexMessageData = stringToHex(messageData); + console.log(`Sending store-only message with data: ${messageData} (hex: ${hexMessageData})`); const sendingFee = await messageBridge.sendingFee(); console.log(`Sending fee: ${sendingFee} wei`); - const hash = await messageBridge.sendStoreOnlyMessage(messageData as `0x${string}`, - { - value: sendingFee - } + const hash = await messageBridge.sendStoreOnlyMessage(hexMessageData, {value: sendingFee} ); console.log('Store-only message sent successfully. Transaction hash:', hash); From 3a3947a39932f820573d5a5cd1ee0e9845cf0b42 Mon Sep 17 00:00:00 2001 From: Otniel Nicola Date: Mon, 2 Feb 2026 14:52:26 +0200 Subject: [PATCH 8/8] feat: Use custom chain for devnet --- src/evm/utils.ts | 28 +++++++++++++++++++++++----- 1 file changed, 23 insertions(+), 5 deletions(-) diff --git a/src/evm/utils.ts b/src/evm/utils.ts index d46e6ae..703300a 100644 --- a/src/evm/utils.ts +++ b/src/evm/utils.ts @@ -7,9 +7,8 @@ import { EvmBridgeManagement, EvmMessageBridgeFactory, EvmNativeBridgeFactory, EvmTokenBridgeFactory, EvmExecutionManagerFactory, EvmBridgeManagementFactory } from "@bane-labs/bridge-sdk-ts"; -import { createPublicClient, createWalletClient, http, type Address, PrivateKeyAccount } from 'viem'; +import { createPublicClient, createWalletClient, http, type Address, PrivateKeyAccount, defineChain } from 'viem'; import { privateKeyToAccount, HDAccount } from 'viem/accounts'; -import { mainnet } from 'viem/chains'; import * as fs from 'fs'; import dotenv from "dotenv"; @@ -17,6 +16,25 @@ export function ensureEnv() { dotenv.config(); } +function getRpcUrl(): string { + return process.env.EVM_RPC_URL || 'http://localhost:8562'; +} + +const customNeoX = defineChain({ + id: 2312051126, + name: 'NeoX Custom', + nativeCurrency: { + decimals: 18, + name: 'GAS', + symbol: 'GAS', + }, + rpcUrls: { + default: { + http: [getRpcUrl()], + }, + }, +}); + async function createAccountFromWalletFile(walletPath: string, password: string): Promise { if (!fs.existsSync(walletPath)) { throw new Error(`Wallet file not found: ${walletPath}`); @@ -33,10 +51,10 @@ async function createAccountFromWalletFile(walletPath: string, password: string) } export async function createEvmContractWrapperConfig(contractAddress: Address): Promise { - const rpcUrl = process.env.EVM_RPC_URL || 'http://localhost:8562'; + const rpcUrl = getRpcUrl(); const publicClient = createPublicClient({ - chain: mainnet, + chain: customNeoX, transport: http(rpcUrl) }); @@ -50,7 +68,7 @@ export async function createEvmContractWrapperConfig(contractAddress: Address): const account = await createAccountFromWalletFile(walletPath, walletPassword); walletClient = createWalletClient({ account, - chain: mainnet, + chain: customNeoX, transport: http(rpcUrl) }); } catch (error) {