diff --git a/package-lock.json b/package-lock.json
index e681f71..bb942f5 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -18,7 +18,7 @@
"@1shotapi/ows-signer-utils": "^0.6.2",
"@1shotapi/ows-types": "^0.8.0",
"@1shotapi/ows-wallet-utils": "^0.5.1",
- "@crcl-main/app-kit": "^1.10.0-canary-feature-onramp-kit-sdk.1784835391",
+ "@crcl-main/app-kit": "^1.14.0-canary-feature-onramp-kit-sdk.1789055534",
"@fontsource-variable/geist": "^5.3.0",
"@metamask/smart-accounts-kit": "^2.0.0",
"@reown/walletkit": "^1.5.6",
@@ -1111,17 +1111,17 @@
}
},
"node_modules/@crcl-main/app-kit": {
- "version": "1.10.0-canary-feature-onramp-kit-sdk.1784835391",
- "resolved": "https://npm.cloudsmith.io/circle/common-private/@crcl-main/app-kit/-/app-kit-1.10.0-canary-feature-onramp-kit-sdk.1784835391.tgz",
- "integrity": "sha512-FfLR6nr/HmqaqSs7ZtCL4jmJzhF4sL+ru0oHGbtO+lcbb3TYBy5vYeuyYgWHQl79e4hCmJUN3xYw20l8PT5MVA==",
+ "version": "1.14.0-canary-feature-onramp-kit-sdk.1789055534",
+ "resolved": "https://npm.cloudsmith.io/circle/common-private/@crcl-main/app-kit/-/app-kit-1.14.0-canary-feature-onramp-kit-sdk.1789055534.tgz",
+ "integrity": "sha512-04GjiZqTZAiNz+KXvafEk/4TS3pXEWfZPk6HUoyKzIwpMsz8JD6ixNeBy4wuBLEcSCNSJd1A9IF25AWoHKODZQ==",
"dependencies": {
"@coral-xyz/anchor": "^0.31.1",
- "@crcl-main/bridge-kit": "1.12.1-canary-feature-onramp-kit-sdk.1784835391",
- "@crcl-main/earn-kit": "1.3.0-canary-feature-onramp-kit-sdk.1784835391",
- "@crcl-main/onramp-kit": "0.0.1-canary-feature-onramp-kit-sdk.1784835391",
- "@crcl-main/provider-gateway-v1": "1.1.3-canary-feature-onramp-kit-sdk.1784835391",
- "@crcl-main/swap-kit": "1.4.0-canary-feature-onramp-kit-sdk.1784835391",
- "@crcl-main/unified-balance-kit": "1.3.0-canary-feature-onramp-kit-sdk.1784835391",
+ "@crcl-main/bridge-kit": "1.14.1-canary-feature-onramp-kit-sdk.1789055534",
+ "@crcl-main/earn-kit": "1.6.1-canary-feature-onramp-kit-sdk.1789055534",
+ "@crcl-main/onramp-kit": "0.0.1-canary-feature-onramp-kit-sdk.1789055534",
+ "@crcl-main/provider-gateway-v1": "1.4.0-canary-feature-onramp-kit-sdk.1789055534",
+ "@crcl-main/swap-kit": "1.6.1-canary-feature-onramp-kit-sdk.1789055534",
+ "@crcl-main/unified-balance-kit": "1.6.0-canary-feature-onramp-kit-sdk.1789055534",
"@ethersproject/abi": "^5.8.0",
"@ethersproject/address": "^5.8.0",
"@ethersproject/bytes": "^5.8.0",
@@ -1196,11 +1196,12 @@
}
},
"node_modules/@crcl-main/bridge-kit": {
- "version": "1.12.1-canary-feature-onramp-kit-sdk.1784835391",
- "resolved": "https://npm.cloudsmith.io/circle/common-private/@crcl-main/bridge-kit/-/bridge-kit-1.12.1-canary-feature-onramp-kit-sdk.1784835391.tgz",
- "integrity": "sha512-z59Mus6FOdFJloXNi5hkzKwHjDFdblave8+e5sDqrDy6tqNBu2aq7uez3vjMfvnqRu5elaBEAAASonm8jQeyGQ==",
+ "version": "1.14.1-canary-feature-onramp-kit-sdk.1789055534",
+ "resolved": "https://npm.cloudsmith.io/circle/common-private/@crcl-main/bridge-kit/-/bridge-kit-1.14.1-canary-feature-onramp-kit-sdk.1789055534.tgz",
+ "integrity": "sha512-oBze4ODsutrppjkhL0jq1JtxdFFgo4qYDSK3yScrDiE3CcohyOom5S8MvN/QY72xUteQKzCiDgXWpQqsB7PaSQ==",
"dependencies": {
- "@crcl-main/provider-cctp-v2": "1.10.0-canary-feature-onramp-kit-sdk.1784835391",
+ "@crcl-main/provider-cctp-v2": "1.13.0-canary-feature-onramp-kit-sdk.1789055534",
+ "@crcl-main/provider-fee-v1": "0.3.0-canary-feature-onramp-kit-sdk.1789055534",
"@ethersproject/abi": "^5.8.0",
"@ethersproject/address": "^5.8.0",
"@ethersproject/bytes": "^5.8.0",
@@ -1247,11 +1248,11 @@
}
},
"node_modules/@crcl-main/earn-kit": {
- "version": "1.3.0-canary-feature-onramp-kit-sdk.1784835391",
- "resolved": "https://npm.cloudsmith.io/circle/common-private/@crcl-main/earn-kit/-/earn-kit-1.3.0-canary-feature-onramp-kit-sdk.1784835391.tgz",
- "integrity": "sha512-IBcDCDN32X3Jy28SP9e5XC8TbJ/UgzBqn8dA/9cAH7ttA0tyCeZTPwMiLXeNI0nHQ5zrJTTY1Sw3latGAFWn/A==",
+ "version": "1.6.1-canary-feature-onramp-kit-sdk.1789055534",
+ "resolved": "https://npm.cloudsmith.io/circle/common-private/@crcl-main/earn-kit/-/earn-kit-1.6.1-canary-feature-onramp-kit-sdk.1789055534.tgz",
+ "integrity": "sha512-5YwMUf2PK8VsFlOoQv38ykp8gDxWbVqQkHFCgb9OaqfHmmPn9f/xwQDdluvAkuA85pj2UI9iJKc00VZyT50a5g==",
"dependencies": {
- "@crcl-main/provider-earn-service": "1.3.0-canary-feature-onramp-kit-sdk.1784835391",
+ "@crcl-main/provider-earn-service": "1.5.1-canary-feature-onramp-kit-sdk.1789055534",
"@ethersproject/abi": "^5.8.0",
"@ethersproject/address": "^5.8.0",
"@ethersproject/bytes": "^5.8.0",
@@ -1299,9 +1300,9 @@
}
},
"node_modules/@crcl-main/onramp-kit": {
- "version": "0.0.1-canary-feature-onramp-kit-sdk.1784835391",
- "resolved": "https://npm.cloudsmith.io/circle/common-private/@crcl-main/onramp-kit/-/onramp-kit-0.0.1-canary-feature-onramp-kit-sdk.1784835391.tgz",
- "integrity": "sha512-72nyxHll7kEMcbL/U3scA39njcVpDQCVfCEQ6EcH+7E964/63m0fHEHfPFmvnNjph5Abneqq32dOsbKlWeYzFg==",
+ "version": "0.0.1-canary-feature-onramp-kit-sdk.1789055534",
+ "resolved": "https://npm.cloudsmith.io/circle/common-private/@crcl-main/onramp-kit/-/onramp-kit-0.0.1-canary-feature-onramp-kit-sdk.1789055534.tgz",
+ "integrity": "sha512-xEpJA3oRgNGOKAZaDcjobmEZnxfDunFjNeWH3gZzCJJrj4mboNHPJVOJMpHPLOErfSBuilZcU+sQuvrwAJ0OrA==",
"dependencies": {
"pino": "10.1.0",
"zod": "3.25.67"
@@ -1342,9 +1343,9 @@
}
},
"node_modules/@crcl-main/provider-cctp-v2": {
- "version": "1.10.0-canary-feature-onramp-kit-sdk.1784835391",
- "resolved": "https://npm.cloudsmith.io/circle/common-private/@crcl-main/provider-cctp-v2/-/provider-cctp-v2-1.10.0-canary-feature-onramp-kit-sdk.1784835391.tgz",
- "integrity": "sha512-232LEFAViDGzIhpC9rD7yiREc1MmvexErEh1lQ/5lkax08/qTULWwi6O70GhMtfIKq9AB0rV8OnpC5GsY4UCeQ==",
+ "version": "1.13.0-canary-feature-onramp-kit-sdk.1789055534",
+ "resolved": "https://npm.cloudsmith.io/circle/common-private/@crcl-main/provider-cctp-v2/-/provider-cctp-v2-1.13.0-canary-feature-onramp-kit-sdk.1789055534.tgz",
+ "integrity": "sha512-Q6HmGkmeGee4OqogbJ9cP/hgfIlj2NNIHh03F5i20Oq8FGag81jbFlaSGTNzMTFMyRSy//zyc8vSANkmeBY2tA==",
"dependencies": {
"@coral-xyz/anchor": "^0.31.1",
"@ethersproject/abi": "^5.8.0",
@@ -1427,9 +1428,9 @@
}
},
"node_modules/@crcl-main/provider-earn-service": {
- "version": "1.3.0-canary-feature-onramp-kit-sdk.1784835391",
- "resolved": "https://npm.cloudsmith.io/circle/common-private/@crcl-main/provider-earn-service/-/provider-earn-service-1.3.0-canary-feature-onramp-kit-sdk.1784835391.tgz",
- "integrity": "sha512-93TzDgvhFMXBn/DOOB0XE0LKg2NGsmn4nfuJhlrpTdtuYVzvRANPthdv7gooDL1St3EfOxnh68gt5YkJlcrBnQ==",
+ "version": "1.5.1-canary-feature-onramp-kit-sdk.1789055534",
+ "resolved": "https://npm.cloudsmith.io/circle/common-private/@crcl-main/provider-earn-service/-/provider-earn-service-1.5.1-canary-feature-onramp-kit-sdk.1789055534.tgz",
+ "integrity": "sha512-YwP9w5ly42cgW1GngCxCfVqLZh0s1INa2ZpzxgKEzsetKUvvIPhyVjGulY7czYeGj5KKHYZ2ZXQqrC9T5qLSpQ==",
"dependencies": {
"@ethersproject/abi": "^5.8.0",
"@ethersproject/address": "^5.8.0",
@@ -1477,10 +1478,35 @@
"url": "https://github.com/sponsors/colinhacks"
}
},
+ "node_modules/@crcl-main/provider-fee-v1": {
+ "version": "0.3.0-canary-feature-onramp-kit-sdk.1789055534",
+ "resolved": "https://npm.cloudsmith.io/circle/common-private/@crcl-main/provider-fee-v1/-/provider-fee-v1-0.3.0-canary-feature-onramp-kit-sdk.1789055534.tgz",
+ "integrity": "sha512-3TFMhB3BQgP632LEN7ZK1GiqeX2aTtwEXR7FdksKOjPwTCrfrzvH9D76aYGzLn4SBR9tV+nQjIQnzJwz5GWz8Q==",
+ "dependencies": {
+ "@ethersproject/abi": "^5.8.0",
+ "@ethersproject/address": "^5.8.0",
+ "@ethersproject/bytes": "^5.8.0",
+ "@ethersproject/units": "^5.8.0",
+ "bs58": "6.0.0",
+ "zod": "3.25.67"
+ },
+ "engines": {
+ "node": ">=20.0.0"
+ }
+ },
+ "node_modules/@crcl-main/provider-fee-v1/node_modules/zod": {
+ "version": "3.25.67",
+ "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.67.tgz",
+ "integrity": "sha512-idA2YXwpCdqUSKRCACDE6ItZD9TZzy3OZMtpfLoh6oPR47lipysRrJfjzMqFxQ3uJuUPyUeWe1r9vLH33xO/Qw==",
+ "license": "MIT",
+ "funding": {
+ "url": "https://github.com/sponsors/colinhacks"
+ }
+ },
"node_modules/@crcl-main/provider-gateway-v1": {
- "version": "1.1.3-canary-feature-onramp-kit-sdk.1784835391",
- "resolved": "https://npm.cloudsmith.io/circle/common-private/@crcl-main/provider-gateway-v1/-/provider-gateway-v1-1.1.3-canary-feature-onramp-kit-sdk.1784835391.tgz",
- "integrity": "sha512-KoDN0Fh1qSt9URuc+/pAEc3szHvB2zk1fNuFgKh6yTAwI70G4orNivo7GpWp6OkPq7vboxpGXvLW0ptepi6KyQ==",
+ "version": "1.4.0-canary-feature-onramp-kit-sdk.1789055534",
+ "resolved": "https://npm.cloudsmith.io/circle/common-private/@crcl-main/provider-gateway-v1/-/provider-gateway-v1-1.4.0-canary-feature-onramp-kit-sdk.1789055534.tgz",
+ "integrity": "sha512-dGq3koCcmVP+Zh1ez0dupDN/Sb0bMt7h+WfWQJGpMcJao/dfGjf3Dx8X366CWgxlYM/emD0RVPEYw7UcakJVxw==",
"dependencies": {
"@coral-xyz/anchor": "^0.31.1",
"@ethersproject/abi": "^5.8.0",
@@ -1493,6 +1519,7 @@
"bn.js": "^5.2.3",
"bs58": "6.0.0",
"buffer": "^6.0.3",
+ "pino": "10.1.0",
"zod": "3.25.67"
},
"engines": {
@@ -1523,6 +1550,28 @@
"url": "https://paulmillr.com/funding/"
}
},
+ "node_modules/@crcl-main/provider-gateway-v1/node_modules/pino": {
+ "version": "10.1.0",
+ "resolved": "https://registry.npmjs.org/pino/-/pino-10.1.0.tgz",
+ "integrity": "sha512-0zZC2ygfdqvqK8zJIr1e+wT1T/L+LF6qvqvbzEQ6tiMAoTqEVK9a1K3YRu8HEUvGEvNqZyPJTtb2sNIoTkB83w==",
+ "license": "MIT",
+ "dependencies": {
+ "@pinojs/redact": "^0.4.0",
+ "atomic-sleep": "^1.0.0",
+ "on-exit-leak-free": "^2.1.0",
+ "pino-abstract-transport": "^2.0.0",
+ "pino-std-serializers": "^7.0.0",
+ "process-warning": "^5.0.0",
+ "quick-format-unescaped": "^4.0.3",
+ "real-require": "^0.2.0",
+ "safe-stable-stringify": "^2.3.1",
+ "sonic-boom": "^4.0.1",
+ "thread-stream": "^3.0.0"
+ },
+ "bin": {
+ "pino": "bin.js"
+ }
+ },
"node_modules/@crcl-main/provider-gateway-v1/node_modules/zod": {
"version": "3.25.67",
"resolved": "https://registry.npmjs.org/zod/-/zod-3.25.67.tgz",
@@ -1533,9 +1582,9 @@
}
},
"node_modules/@crcl-main/provider-stablecoin-service-swap": {
- "version": "1.3.0-canary-feature-onramp-kit-sdk.1784835391",
- "resolved": "https://npm.cloudsmith.io/circle/common-private/@crcl-main/provider-stablecoin-service-swap/-/provider-stablecoin-service-swap-1.3.0-canary-feature-onramp-kit-sdk.1784835391.tgz",
- "integrity": "sha512-DcE2yoS7CPbsmkbJpX+QMoLVSjMPrXkQub8xNVN+YzKxKPwHmKwLN5naQ6QV5Te6soxbMUPOBpHqkDo/yKO/lA==",
+ "version": "1.5.1-canary-feature-onramp-kit-sdk.1789055534",
+ "resolved": "https://npm.cloudsmith.io/circle/common-private/@crcl-main/provider-stablecoin-service-swap/-/provider-stablecoin-service-swap-1.5.1-canary-feature-onramp-kit-sdk.1789055534.tgz",
+ "integrity": "sha512-lgwYtOhKQ61kHOtkoV5YtPzLjSx5xrUrE2UwK4K0q84ecoMF6oS6r4q6SHNeopVHxakaDMHVM7ZHUghLGz2KEA==",
"dependencies": {
"@coral-xyz/anchor": "^0.31.1",
"@ethersproject/address": "^5.8.0",
@@ -1586,12 +1635,12 @@
}
},
"node_modules/@crcl-main/swap-kit": {
- "version": "1.4.0-canary-feature-onramp-kit-sdk.1784835391",
- "resolved": "https://npm.cloudsmith.io/circle/common-private/@crcl-main/swap-kit/-/swap-kit-1.4.0-canary-feature-onramp-kit-sdk.1784835391.tgz",
- "integrity": "sha512-MWDSp2iJ5aMSer+mlRiDPteqUo9QLNY/krQGS4ZlaEz5ndf7ceGCtBjHdNh7Yf1Fp828BYBoQQE1EFcNk13ALA==",
+ "version": "1.6.1-canary-feature-onramp-kit-sdk.1789055534",
+ "resolved": "https://npm.cloudsmith.io/circle/common-private/@crcl-main/swap-kit/-/swap-kit-1.6.1-canary-feature-onramp-kit-sdk.1789055534.tgz",
+ "integrity": "sha512-I6VqJ5oml3Rh2SnE/VHm/B17KFFNx6naMuYv1Hgaem783e7812lSlWZ17dwxMz2wnJ2/CNzzM6vrrMn0BOQkSQ==",
"dependencies": {
"@coral-xyz/anchor": "^0.31.1",
- "@crcl-main/provider-stablecoin-service-swap": "1.3.0-canary-feature-onramp-kit-sdk.1784835391",
+ "@crcl-main/provider-stablecoin-service-swap": "1.5.1-canary-feature-onramp-kit-sdk.1789055534",
"@ethersproject/abi": "^5.8.0",
"@ethersproject/address": "^5.8.0",
"@ethersproject/bytes": "^5.8.0",
@@ -1641,12 +1690,14 @@
}
},
"node_modules/@crcl-main/unified-balance-kit": {
- "version": "1.3.0-canary-feature-onramp-kit-sdk.1784835391",
- "resolved": "https://npm.cloudsmith.io/circle/common-private/@crcl-main/unified-balance-kit/-/unified-balance-kit-1.3.0-canary-feature-onramp-kit-sdk.1784835391.tgz",
- "integrity": "sha512-OX19leoAPWlSygx75jbROHZahcMI6y27wlUaBdaCe1IeUHgGM1YrqGuLngmC1eTGC5fmA4Sl+SrJ4v5HrVKpCQ==",
+ "version": "1.6.0-canary-feature-onramp-kit-sdk.1789055534",
+ "resolved": "https://npm.cloudsmith.io/circle/common-private/@crcl-main/unified-balance-kit/-/unified-balance-kit-1.6.0-canary-feature-onramp-kit-sdk.1789055534.tgz",
+ "integrity": "sha512-fFOiusRzjGdXcti/bOkMu1aPYQowtC9VJ9QxCaBjfoIT8hf/szl9k/i0DAEpFZeTWRcOiiGznH8orM/hjoNF1A==",
"dependencies": {
"@coral-xyz/anchor": "^0.31.1",
- "@crcl-main/provider-gateway-v1": "1.1.3-canary-feature-onramp-kit-sdk.1784835391",
+ "@crcl-main/provider-cctp-v2": "1.13.0-canary-feature-onramp-kit-sdk.1789055534",
+ "@crcl-main/provider-fee-v1": "0.3.0-canary-feature-onramp-kit-sdk.1789055534",
+ "@crcl-main/provider-gateway-v1": "1.4.0-canary-feature-onramp-kit-sdk.1789055534",
"@ethersproject/abi": "^5.8.0",
"@ethersproject/address": "^5.8.0",
"@ethersproject/bytes": "^5.8.0",
@@ -1656,6 +1707,7 @@
"abitype": "^1.1.0",
"bn.js": "^5.2.3",
"bs58": "6.0.0",
+ "uuid": "^14.0.1",
"zod": "3.25.67"
},
"engines": {
@@ -1686,6 +1738,19 @@
"url": "https://paulmillr.com/funding/"
}
},
+ "node_modules/@crcl-main/unified-balance-kit/node_modules/uuid": {
+ "version": "14.0.2",
+ "resolved": "https://registry.npmjs.org/uuid/-/uuid-14.0.2.tgz",
+ "integrity": "sha512-xZe/16rV4aa+HGSOCiY2YeLT1OybRLrrkL/Rqaq7p7GMVXjFh+6wN4oMYgjFmnSnhY8t6Xpdl2l9qmnHYuMHwQ==",
+ "funding": [
+ "https://github.com/sponsors/broofa",
+ "https://github.com/sponsors/ctavan"
+ ],
+ "license": "MIT",
+ "bin": {
+ "uuid": "dist-node/bin/uuid"
+ }
+ },
"node_modules/@crcl-main/unified-balance-kit/node_modules/zod": {
"version": "3.25.67",
"resolved": "https://registry.npmjs.org/zod/-/zod-3.25.67.tgz",
@@ -7044,44 +7109,54 @@
}
},
"node_modules/@solana/codecs-core": {
- "version": "2.3.0",
- "resolved": "https://registry.npmjs.org/@solana/codecs-core/-/codecs-core-2.3.0.tgz",
- "integrity": "sha512-oG+VZzN6YhBHIoSKgS5ESM9VIGzhWjEHEGNPSibiDTxFhsFWxNaz8LbMDPjBUE69r9wmdGLkrQ+wVPbnJcZPvw==",
+ "version": "5.5.1",
+ "resolved": "https://registry.npmjs.org/@solana/codecs-core/-/codecs-core-5.5.1.tgz",
+ "integrity": "sha512-TgBt//bbKBct0t6/MpA8ElaOA3sa8eYVvR7LGslCZ84WiAwwjCY0lW/lOYsFHJQzwREMdUyuEyy5YWBKtdh8Rw==",
"license": "MIT",
"dependencies": {
- "@solana/errors": "2.3.0"
+ "@solana/errors": "5.5.1"
},
"engines": {
"node": ">=20.18.0"
},
"peerDependencies": {
- "typescript": ">=5.3.3"
+ "typescript": "^5.0.0"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
}
},
"node_modules/@solana/codecs-numbers": {
- "version": "2.3.0",
- "resolved": "https://registry.npmjs.org/@solana/codecs-numbers/-/codecs-numbers-2.3.0.tgz",
- "integrity": "sha512-jFvvwKJKffvG7Iz9dmN51OGB7JBcy2CJ6Xf3NqD/VP90xak66m/Lg48T01u5IQ/hc15mChVHiBm+HHuOFDUrQg==",
+ "version": "5.5.1",
+ "resolved": "https://registry.npmjs.org/@solana/codecs-numbers/-/codecs-numbers-5.5.1.tgz",
+ "integrity": "sha512-rllMIZAHqmtvC0HO/dc/21wDuWaD0B8Ryv8o+YtsICQBuiL/0U4AGwH7Pi5GNFySYk0/crSuwfIqQFtmxNSPFw==",
"license": "MIT",
"dependencies": {
- "@solana/codecs-core": "2.3.0",
- "@solana/errors": "2.3.0"
+ "@solana/codecs-core": "5.5.1",
+ "@solana/errors": "5.5.1"
},
"engines": {
"node": ">=20.18.0"
},
"peerDependencies": {
- "typescript": ">=5.3.3"
+ "typescript": "^5.0.0"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
}
},
"node_modules/@solana/errors": {
- "version": "2.3.0",
- "resolved": "https://registry.npmjs.org/@solana/errors/-/errors-2.3.0.tgz",
- "integrity": "sha512-66RI9MAbwYV0UtP7kGcTBVLxJgUxoZGm8Fbc0ah+lGiAw17Gugco6+9GrJCV83VyF2mDWyYnYM9qdI3yjgpnaQ==",
+ "version": "5.5.1",
+ "resolved": "https://registry.npmjs.org/@solana/errors/-/errors-5.5.1.tgz",
+ "integrity": "sha512-vFO3p+S7HoyyrcAectnXbdsMfwUzY2zYFUc2DEe5BwpiE9J1IAxPBGjOWO6hL1bbYdBrlmjNx8DXCslqS+Kcmg==",
"license": "MIT",
"dependencies": {
- "chalk": "^5.4.1",
- "commander": "^14.0.0"
+ "chalk": "5.6.2",
+ "commander": "14.0.2"
},
"bin": {
"errors": "bin/cli.mjs"
@@ -7090,32 +7165,61 @@
"node": ">=20.18.0"
},
"peerDependencies": {
- "typescript": ">=5.3.3"
+ "typescript": "^5.0.0"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@solana/errors/node_modules/commander": {
+ "version": "14.0.2",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-14.0.2.tgz",
+ "integrity": "sha512-TywoWNNRbhoD0BXs1P3ZEScW8W5iKrnbithIl0YH+uCmBd0QpPOA8yc82DS3BIE5Ma6FnBVUsJ7wVUDz4dvOWQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=20"
}
},
"node_modules/@solana/web3.js": {
- "version": "1.98.4",
- "resolved": "https://registry.npmjs.org/@solana/web3.js/-/web3.js-1.98.4.tgz",
- "integrity": "sha512-vv9lfnvjUsRiq//+j5pBdXig0IQdtzA0BRZ3bXEP4KaIyF1CcaydWqgyzQgfZMNIsWNWmG+AUHwPy4AHOD6gpw==",
+ "version": "1.99.0",
+ "resolved": "https://registry.npmjs.org/@solana/web3.js/-/web3.js-1.99.0.tgz",
+ "integrity": "sha512-QZYQ2T1z6xWisoyALPq25i/QZTsRlM02BABtAsfaQ1p8wX4SdTfxrKTRue/ZZqrhNVh5oL7T/DUFiTS9DRgxow==",
"license": "MIT",
"dependencies": {
- "@babel/runtime": "^7.25.0",
- "@noble/curves": "^1.4.2",
- "@noble/hashes": "^1.4.0",
+ "@babel/runtime": "^7.29.7",
+ "@noble/curves": "^1.9.7",
+ "@noble/hashes": "^1.8.0",
"@solana/buffer-layout": "^4.0.1",
- "@solana/codecs-numbers": "^2.1.0",
- "agentkeepalive": "^4.5.0",
- "bn.js": "^5.2.1",
+ "@solana/codecs-numbers": "^5.5.1",
+ "agentkeepalive": "^4.6.0",
+ "bn.js": "^5.2.5",
"borsh": "^0.7.0",
"bs58": "^4.0.1",
"buffer": "6.0.3",
"fast-stable-stringify": "^1.0.0",
- "jayson": "^4.1.1",
+ "jayson": "^4.3.0",
"node-fetch": "^2.7.0",
"rpc-websockets": "^9.0.2",
"superstruct": "^2.0.2"
}
},
+ "node_modules/@solana/web3.js/node_modules/@noble/curves": {
+ "version": "1.9.7",
+ "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.9.7.tgz",
+ "integrity": "sha512-gbKGcRUYIjA3/zCCNaWDciTMFI0dCkvou3TL8Zmy5Nc7sJ47a0jtOeZoTaMxkuqRo9cRhjOdZJXegxYE5FN/xw==",
+ "license": "MIT",
+ "dependencies": {
+ "@noble/hashes": "1.8.0"
+ },
+ "engines": {
+ "node": "^14.21.3 || >=16"
+ },
+ "funding": {
+ "url": "https://paulmillr.com/funding/"
+ }
+ },
"node_modules/@solana/web3.js/node_modules/base-x": {
"version": "3.0.11",
"resolved": "https://registry.npmjs.org/base-x/-/base-x-3.0.11.tgz",
@@ -14555,9 +14659,9 @@
}
},
"node_modules/rpc-websockets/node_modules/uuid": {
- "version": "14.0.1",
- "resolved": "https://registry.npmjs.org/uuid/-/uuid-14.0.1.tgz",
- "integrity": "sha512-6ZxzVpzDXDa3bJWaHilVayA+BH/1zmxCJoVgvmqJnid/gPoKHxUrS/aC/T6LGQtNHT+XHG9fXPJB4d+IrU30Ew==",
+ "version": "14.0.2",
+ "resolved": "https://registry.npmjs.org/uuid/-/uuid-14.0.2.tgz",
+ "integrity": "sha512-xZe/16rV4aa+HGSOCiY2YeLT1OybRLrrkL/Rqaq7p7GMVXjFh+6wN4oMYgjFmnSnhY8t6Xpdl2l9qmnHYuMHwQ==",
"funding": [
"https://github.com/sponsors/broofa",
"https://github.com/sponsors/ctavan"
@@ -15448,6 +15552,7 @@
"version": "5.8.3",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.3.tgz",
"integrity": "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==",
+ "devOptional": true,
"license": "Apache-2.0",
"bin": {
"tsc": "bin/tsc",
diff --git a/package.json b/package.json
index b541f55..266a27e 100644
--- a/package.json
+++ b/package.json
@@ -30,7 +30,7 @@
"@1shotapi/ows-signer-utils": "^0.6.2",
"@1shotapi/ows-types": "^0.8.0",
"@1shotapi/ows-wallet-utils": "^0.5.1",
- "@crcl-main/app-kit": "^1.10.0-canary-feature-onramp-kit-sdk.1784835391",
+ "@crcl-main/app-kit": "^1.14.0-canary-feature-onramp-kit-sdk.1789055534",
"@fontsource-variable/geist": "^5.3.0",
"@metamask/smart-accounts-kit": "^2.0.0",
"@reown/walletkit": "^1.5.6",
diff --git a/src/components/AssetDetails.tsx b/src/components/AssetDetails.tsx
index 5a1fd6c..d302394 100644
--- a/src/components/AssetDetails.tsx
+++ b/src/components/AssetDetails.tsx
@@ -71,6 +71,8 @@ export function AssetDetails({ asset: assetProp }: IAssetDetailsProps) {
decimals,
assetProp.id,
balance,
+ assetProp.iconUrl,
+ assetProp.weight,
);
useEffect(() => {
@@ -162,6 +164,7 @@ export function AssetDetails({ asset: assetProp }: IAssetDetailsProps) {
chainId={asset.chainId}
address={asset.address}
symbol={asset.symbol}
+ iconUrl={asset.iconUrl}
chainLogoUrl={chain?.logoUrl}
/>
@@ -175,7 +178,10 @@ export function AssetDetails({ asset: assetProp }: IAssetDetailsProps) {
balance={asset.balance}
decimals={asset.decimals}
fallback={
- asset.type !== EAssetType.Erc20 ? copy.balanceNonErc20 : undefined
+ asset.type !== EAssetType.Erc20 &&
+ asset.type !== EAssetType.Native
+ ? copy.balanceNonErc20
+ : undefined
}
className="text-primary text-3xl font-semibold tracking-tight"
/>
diff --git a/src/components/balances/AssetList.tsx b/src/components/balances/AssetList.tsx
index dad14b6..44311e4 100644
--- a/src/components/balances/AssetList.tsx
+++ b/src/components/balances/AssetList.tsx
@@ -97,6 +97,7 @@ export function AssetList({
chainId={row.original.chainId}
address={row.original.address}
symbol={row.original.symbol}
+ iconUrl={row.original.iconUrl}
/>
{row.original.symbol}
@@ -112,7 +113,8 @@ export function AssetList({
balance={row.original.balance}
decimals={row.original.decimals}
fallback={
- row.original.type !== EAssetType.Erc20
+ row.original.type !== EAssetType.Erc20 &&
+ row.original.type !== EAssetType.Native
? copy.balanceNonErc20
: undefined
}
diff --git a/src/lib/implementations/data/HardcodedChainRepository.ts b/src/lib/implementations/data/HardcodedChainRepository.ts
index 2b064e1..6d8739b 100644
--- a/src/lib/implementations/data/HardcodedChainRepository.ts
+++ b/src/lib/implementations/data/HardcodedChainRepository.ts
@@ -5,7 +5,10 @@ import {
} from "@1shotapi/ows-types";
import { EnableArcMainnet } from "../../features";
import type { IChainRepository } from "../../interfaces/data/IChainRepository";
-import { SupportedChain } from "../../types/domain/SupportedChain";
+import {
+ type INativeCurrency,
+ SupportedChain,
+} from "../../types/domain/SupportedChain";
import { EChain } from "../../types/enum/EChain";
import { EChainNetworkType } from "../../types/enum/EChainNetworkType";
import { ChainDisplayUtils } from "../utils/ChainDisplayUtils";
@@ -37,6 +40,49 @@ const ALCHEMY_KEY = "jqLUTbHeN_cVsIX2W7tJk";
* endpoints from config — this catalog value is informational only.
*/
const BITCOIN_RPC_URL = "https://rpc.ankr.com/btc";
+
+const NATIVE_ETH: INativeCurrency = {
+ name: "Ether",
+ symbol: "ETH",
+ decimals: 18,
+};
+const NATIVE_BTC: INativeCurrency = {
+ name: "Bitcoin",
+ symbol: "BTC",
+ decimals: 8,
+};
+/** Arc uses USDC as gas — no separate Native tracked row (see known assets). */
+const NATIVE_ARC_USDC: INativeCurrency = {
+ name: "USDC",
+ symbol: "USDC",
+ decimals: 6,
+};
+const NATIVE_BNB: INativeCurrency = {
+ name: "BNB",
+ symbol: "BNB",
+ decimals: 18,
+};
+const NATIVE_POL: INativeCurrency = {
+ name: "POL",
+ symbol: "POL",
+ decimals: 18,
+};
+const NATIVE_S: INativeCurrency = {
+ name: "Sonic",
+ symbol: "S",
+ decimals: 18,
+};
+const NATIVE_MON: INativeCurrency = {
+ name: "Monad",
+ symbol: "MON",
+ decimals: 18,
+};
+const NATIVE_CELO: INativeCurrency = {
+ name: "CELO",
+ symbol: "CELO",
+ decimals: 18,
+};
+
/**
* Public Relayer docs networks + Arc Testnet (dev relayer) + Robinhood.
* `weight` controls order within Mainnet/Testnet groups (higher = first).
@@ -54,6 +100,7 @@ const CATALOG: readonly SupportedChain[] = [
"Arc",
"https://explorer.arc.io",
false,
+ NATIVE_ARC_USDC,
100,
),
new SupportedChain(
@@ -67,6 +114,7 @@ const CATALOG: readonly SupportedChain[] = [
"Arc Testnet",
"https://testnet.arcscan.app",
true,
+ NATIVE_ARC_USDC,
100,
),
new SupportedChain(
@@ -80,6 +128,7 @@ const CATALOG: readonly SupportedChain[] = [
"Sepolia",
"https://sepolia.etherscan.io",
true,
+ NATIVE_ETH,
80,
),
new SupportedChain(
@@ -93,6 +142,7 @@ const CATALOG: readonly SupportedChain[] = [
"Base Sepolia",
"https://sepolia.basescan.org",
true,
+ NATIVE_ETH,
90,
),
new SupportedChain(
@@ -106,6 +156,7 @@ const CATALOG: readonly SupportedChain[] = [
"Bitcoin Testnet",
"https://mempool.space/testnet",
false,
+ NATIVE_BTC,
75,
),
new SupportedChain(
@@ -119,6 +170,7 @@ const CATALOG: readonly SupportedChain[] = [
"Bitcoin",
"https://mempool.space",
false,
+ NATIVE_BTC,
85,
),
new SupportedChain(
@@ -132,6 +184,7 @@ const CATALOG: readonly SupportedChain[] = [
"Ethereum",
"https://etherscan.io",
true,
+ NATIVE_ETH,
80,
),
new SupportedChain(
@@ -145,6 +198,7 @@ const CATALOG: readonly SupportedChain[] = [
"Linea",
"https://lineascan.build",
true,
+ NATIVE_ETH,
),
new SupportedChain(
EChain.Arbitrum,
@@ -157,6 +211,7 @@ const CATALOG: readonly SupportedChain[] = [
"Arbitrum",
"https://arbiscan.io",
true,
+ NATIVE_ETH,
),
new SupportedChain(
EChain.Optimism,
@@ -169,6 +224,7 @@ const CATALOG: readonly SupportedChain[] = [
"Optimism",
"https://optimistic.etherscan.io",
true,
+ NATIVE_ETH,
),
new SupportedChain(
EChain.Bsc,
@@ -181,6 +237,7 @@ const CATALOG: readonly SupportedChain[] = [
"BSC",
"https://bscscan.com",
false,
+ NATIVE_BNB,
),
new SupportedChain(
EChain.Base,
@@ -193,6 +250,7 @@ const CATALOG: readonly SupportedChain[] = [
"Base",
"https://basescan.org",
true,
+ NATIVE_ETH,
90,
),
new SupportedChain(
@@ -206,6 +264,7 @@ const CATALOG: readonly SupportedChain[] = [
"Polygon",
"https://polygonscan.com",
true,
+ NATIVE_POL,
),
new SupportedChain(
EChain.Sonic,
@@ -218,6 +277,7 @@ const CATALOG: readonly SupportedChain[] = [
"Sonic",
"https://sonicscan.org",
true,
+ NATIVE_S,
),
new SupportedChain(
EChain.Unichain,
@@ -230,6 +290,7 @@ const CATALOG: readonly SupportedChain[] = [
"Unichain",
"https://uniscan.xyz",
true,
+ NATIVE_ETH,
),
new SupportedChain(
EChain.Monad,
@@ -242,6 +303,7 @@ const CATALOG: readonly SupportedChain[] = [
"Monad",
"https://monadvision.com",
true,
+ NATIVE_MON,
),
new SupportedChain(
EChain.Celo,
@@ -254,6 +316,7 @@ const CATALOG: readonly SupportedChain[] = [
"Celo",
"https://celoscan.io",
false,
+ NATIVE_CELO,
),
new SupportedChain(
EChain.Robinhood,
@@ -266,6 +329,7 @@ const CATALOG: readonly SupportedChain[] = [
"Robinhood",
"https://robinhoodchain.blockscout.com",
false,
+ NATIVE_ETH,
),
];
diff --git a/src/lib/implementations/data/HardcodedKnownAssetRepository.ts b/src/lib/implementations/data/HardcodedKnownAssetRepository.ts
index 9809993..5d644d3 100644
--- a/src/lib/implementations/data/HardcodedKnownAssetRepository.ts
+++ b/src/lib/implementations/data/HardcodedKnownAssetRepository.ts
@@ -1,27 +1,76 @@
-import { erc20Abi } from "viem";
-import type {
- EVMAccountAddress as EVMAccountAddressType,
- EVMChainId as EVMChainIdType,
+import { erc20Abi, zeroAddress } from "viem";
+import {
+ ChainUtils,
+ EVMAccountAddress,
+ type EVMAccountAddress as EVMAccountAddressType,
+ type EVMChainId as EVMChainIdType,
} from "@1shotapi/ows-types";
import type { IBlockchainProvider } from "@1shotapi/ows-wallet-utils";
import type { IKnownAssetRepository } from "../../interfaces/data/IKnownAssetRepository";
import { KnownAsset } from "../../types/domain/KnownAsset";
import { NewTrackedAsset } from "../../types/domain/TrackedAsset";
import { EAssetType } from "../../types/enum/EAssetType";
-import { makeTrackedAssetId } from "@/lib/types/primitives";
import { EChain } from "../../types/enum/EChain";
+import { makeTrackedAssetId } from "@/lib/types/primitives";
import {
RELAYER_KNOWN_ASSETS,
getCctpBridgeAsset as lookupCctpBridgeAsset,
} from "./relayerKnownAssets";
+import { HardcodedChainRepository } from "./HardcodedChainRepository";
+import { registerKnownAssetIconResolver } from "../../utils/tokenIcons";
+
+const NATIVE_ADDRESS = EVMAccountAddress(zeroAddress);
+const NATIVE_WEIGHT = 50;
+
+/** Arc gas is the pinned USDC ERC-20 — do not also show a zero-address Native row. */
+const SKIP_NATIVE_DEFAULT = new Set([
+ String(EChain.Arc).toLowerCase(),
+ String(EChain.ArcTestnet).toLowerCase(),
+]);
+
+function buildNativeKnownAssets(): KnownAsset[] {
+ const catalog = new HardcodedChainRepository().getCatalog();
+ const natives: KnownAsset[] = [];
+ for (const chain of catalog) {
+ if (!ChainUtils.isEVMChainId(chain.chainId)) continue;
+ const key = String(chain.chainId).toLowerCase();
+ if (SKIP_NATIVE_DEFAULT.has(key)) continue;
+ natives.push(
+ new KnownAsset(
+ chain.chainId,
+ NATIVE_ADDRESS,
+ EAssetType.Native,
+ chain.nativeCurrency.name,
+ chain.nativeCurrency.symbol,
+ chain.nativeCurrency.decimals,
+ false,
+ NATIVE_WEIGHT,
+ chain.logoUrl,
+ ),
+ );
+ }
+ return natives;
+}
+
+const NATIVE_KNOWN_ASSETS: readonly KnownAsset[] = buildNativeKnownAssets();
+
+const ALL_KNOWN_ASSETS: readonly KnownAsset[] = [
+ ...RELAYER_KNOWN_ASSETS,
+ ...NATIVE_KNOWN_ASSETS,
+];
const BY_KEY = new Map(
- RELAYER_KNOWN_ASSETS.map((asset) => [
+ ALL_KNOWN_ASSETS.map((asset) => [
makeTrackedAssetId(asset.chainId, asset.address),
asset,
]),
);
+// Include native (chain logo) rows in the known-asset icon resolver.
+registerKnownAssetIconResolver(
+ (chainId, address) => BY_KEY.get(makeTrackedAssetId(chainId, address))?.iconUrl,
+);
+
/** Chain → pinned default stablecoin symbol (always shown, not removable). */
const DEFAULT_TRACKED_STABLE_BY_CHAIN = new Map([
[String(EChain.ArcTestnet).toLowerCase(), "USDC"],
@@ -31,29 +80,42 @@ const DEFAULT_TRACKED_STABLE_BY_CHAIN = new Map([
[String(EChain.Robinhood).toLowerCase(), "USDG"],
]);
+function isPinnedStable(asset: KnownAsset): boolean {
+ const expected = DEFAULT_TRACKED_STABLE_BY_CHAIN.get(
+ String(asset.chainId).toLowerCase(),
+ );
+ return (
+ expected != null &&
+ asset.type === EAssetType.Erc20 &&
+ asset.symbol === expected
+ );
+}
+
/**
- * Default stablecoin on demo chains — always shown in Balances (not removable).
- * USDC where listed; USDG on Robinhood (USDC is not deployed there).
+ * Pinned Balances rows: default stables (weight 100) then natives (weight 50),
+ * sorted by weight desc. Not removable.
*/
-export const DEFAULT_TRACKED_USDC: readonly NewTrackedAsset[] =
- RELAYER_KNOWN_ASSETS.filter((asset) => {
- const expected = DEFAULT_TRACKED_STABLE_BY_CHAIN.get(
- String(asset.chainId).toLowerCase(),
- );
- return expected != null && asset.symbol === expected;
- }).map((asset) => NewTrackedAsset.fromKnown(asset));
+export const DEFAULT_TRACKED_ASSETS: readonly NewTrackedAsset[] = [
+ ...RELAYER_KNOWN_ASSETS.filter(isPinnedStable),
+ ...NATIVE_KNOWN_ASSETS,
+]
+ .sort((a, b) => {
+ if (b.weight !== a.weight) return b.weight - a.weight;
+ return a.symbol.localeCompare(b.symbol);
+ })
+ .map((asset) => NewTrackedAsset.fromKnown(asset));
-const DEFAULT_TRACKED_USDC_KEYS = new Set(
- DEFAULT_TRACKED_USDC.map((asset) =>
+const DEFAULT_TRACKED_KEYS = new Set(
+ DEFAULT_TRACKED_ASSETS.map((asset) =>
makeTrackedAssetId(asset.chainId, asset.address),
),
);
-export function isDefaultTrackedUsdc(
+export function isDefaultTrackedAsset(
chainId: EVMChainIdType,
address: EVMAccountAddressType,
): boolean {
- return DEFAULT_TRACKED_USDC_KEYS.has(makeTrackedAssetId(chainId, address));
+ return DEFAULT_TRACKED_KEYS.has(makeTrackedAssetId(chainId, address));
}
export class HardcodedKnownAssetRepository implements IKnownAssetRepository {
@@ -78,7 +140,10 @@ export class HardcodedKnownAssetRepository implements IKnownAssetRepository {
owner: EVMAccountAddressType,
): Promise {
const known = await this.getKnownAsset(chainId, address);
- if (known?.type === EAssetType.Erc20) {
+ if (
+ known?.type === EAssetType.Erc20 ||
+ known?.type === EAssetType.Native
+ ) {
return NewTrackedAsset.fromKnown(known);
}
diff --git a/src/lib/implementations/data/LocalStorageTrackedAssetRepository.ts b/src/lib/implementations/data/LocalStorageTrackedAssetRepository.ts
index 828b63e..f33ef84 100644
--- a/src/lib/implementations/data/LocalStorageTrackedAssetRepository.ts
+++ b/src/lib/implementations/data/LocalStorageTrackedAssetRepository.ts
@@ -14,8 +14,8 @@ import type { IConfigProvider } from "../../interfaces/utils/IConfigProvider";
import type { IEventBus } from "../../interfaces/utils/IEventBus";
import type { ITrackedAssetRepository } from "../../interfaces/data/ITrackedAssetRepository";
import {
- DEFAULT_TRACKED_USDC,
- isDefaultTrackedUsdc,
+ DEFAULT_TRACKED_ASSETS,
+ isDefaultTrackedAsset,
} from "./HardcodedKnownAssetRepository";
import { NewTrackedAsset, TrackedAsset } from "../../types/domain/TrackedAsset";
import { EAssetType } from "../../types/enum/EAssetType";
@@ -89,7 +89,7 @@ export class LocalStorageTrackedAssetRepository
chainId: EVMChainIdType,
address: EVMAccountAddressType,
): Promise {
- if (isDefaultTrackedUsdc(chainId, address)) {
+ if (isDefaultTrackedAsset(chainId, address)) {
return true;
}
const storageKey = await this.resolveStorageKey();
@@ -101,7 +101,7 @@ export class LocalStorageTrackedAssetRepository
asset: NewTrackedAsset,
owner: EVMAccountAddressType,
): Promise {
- if (isDefaultTrackedUsdc(asset.chainId, asset.address)) {
+ if (isDefaultTrackedAsset(asset.chainId, asset.address)) {
const existing = TrackedAsset.fromNew(asset);
const [withBalance] = await this.ensureBalances([existing], owner, false);
return withBalance!;
@@ -146,7 +146,7 @@ export class LocalStorageTrackedAssetRepository
chainId: EVMChainIdType,
address: EVMAccountAddressType,
): Promise {
- if (isDefaultTrackedUsdc(chainId, address)) {
+ if (isDefaultTrackedAsset(chainId, address)) {
return;
}
const storageKey = await this.resolveStorageKey();
@@ -178,7 +178,7 @@ export class LocalStorageTrackedAssetRepository
private mergeWithDefaults(stored: TrackedAsset[]): TrackedAsset[] {
const seen = new Set();
const merged: TrackedAsset[] = [];
- for (const asset of DEFAULT_TRACKED_USDC) {
+ for (const asset of DEFAULT_TRACKED_ASSETS) {
const key = makeTrackedAssetId(asset.chainId, asset.address);
seen.add(key);
merged.push(TrackedAsset.fromNew(asset));
@@ -223,10 +223,19 @@ export class LocalStorageTrackedAssetRepository
asset: TrackedAsset,
owner: EVMAccountAddressType,
): Promise {
- if (asset.type !== EAssetType.Erc20) {
+ if (owner === EMPTY_OWNER) {
return null;
}
- if (owner === EMPTY_OWNER) {
+ if (asset.type === EAssetType.Native) {
+ try {
+ const client = this.blockchain.getPublicClient(asset.chainId);
+ return await client.getBalance({ address: owner as Address });
+ } catch (error: unknown) {
+ console.warn("[balances] getBalance failed", error);
+ return null;
+ }
+ }
+ if (asset.type !== EAssetType.Erc20) {
return null;
}
try {
@@ -265,11 +274,13 @@ export class LocalStorageTrackedAssetRepository
const chainId = EVMChainId(row.chainId as `0x${string}`);
const address = EVMAccountAddress(row.address as `0x${string}`);
const type =
- row.type === EAssetType.Erc721
- ? EAssetType.Erc721
- : row.type === EAssetType.Erc1155
- ? EAssetType.Erc1155
- : EAssetType.Erc20;
+ row.type === EAssetType.Native
+ ? EAssetType.Native
+ : row.type === EAssetType.Erc721
+ ? EAssetType.Erc721
+ : row.type === EAssetType.Erc1155
+ ? EAssetType.Erc1155
+ : EAssetType.Erc20;
const iconUrl =
typeof row.iconUrl === "string" && row.iconUrl.length > 0
? row.iconUrl
@@ -297,7 +308,7 @@ export class LocalStorageTrackedAssetRepository
private writeAssets(storageKey: string, assets: TrackedAsset[]): void {
// Persist only user-added (non-default) rows as NewTrackedAsset fields + id.
const userAssets = assets.filter(
- (asset) => !isDefaultTrackedUsdc(asset.chainId, asset.address),
+ (asset) => !isDefaultTrackedAsset(asset.chainId, asset.address),
);
const blob: StoredBlob = {
assets: userAssets.map((asset) => ({
diff --git a/src/lib/implementations/data/index.ts b/src/lib/implementations/data/index.ts
index 8a46bd5..ba29d00 100644
--- a/src/lib/implementations/data/index.ts
+++ b/src/lib/implementations/data/index.ts
@@ -1,7 +1,7 @@
export {
- DEFAULT_TRACKED_USDC,
+ DEFAULT_TRACKED_ASSETS,
HardcodedKnownAssetRepository,
- isDefaultTrackedUsdc,
+ isDefaultTrackedAsset,
} from "./HardcodedKnownAssetRepository";
export { LocalStorageTrackedAssetRepository } from "./LocalStorageTrackedAssetRepository";
export type { TrackedAssetRepositoryOptions } from "./LocalStorageTrackedAssetRepository";
diff --git a/src/lib/implementations/data/relayerKnownAssets.ts b/src/lib/implementations/data/relayerKnownAssets.ts
index 0ada8fa..1c96ea5 100644
--- a/src/lib/implementations/data/relayerKnownAssets.ts
+++ b/src/lib/implementations/data/relayerKnownAssets.ts
@@ -19,6 +19,8 @@ type ISeedRow = {
name: string;
decimals: number;
useCCTPBridge?: boolean;
+ /** Pinned default stables use 100 so they sort above native (50). */
+ weight?: number;
};
function seed(row: ISeedRow): KnownAsset {
@@ -30,6 +32,7 @@ function seed(row: ISeedRow): KnownAsset {
row.symbol,
row.decimals,
row.useCCTPBridge === true,
+ row.weight ?? 0,
iconUrlForSymbol(row.symbol),
);
}
@@ -50,6 +53,7 @@ const SEED_ROWS: readonly ISeedRow[] = [
name: "USDC",
decimals: 6,
useCCTPBridge: true,
+ weight: 100,
},
// Robinhood (4663) — official USDG (USDC is not deployed)
{
@@ -60,6 +64,7 @@ const SEED_ROWS: readonly ISeedRow[] = [
symbol: "USDG",
name: "Global Dollar",
decimals: 6,
+ weight: 100,
},
// Ethereum mainnet (1)
{
@@ -219,6 +224,7 @@ const SEED_ROWS: readonly ISeedRow[] = [
name: "USD Coin",
decimals: 6,
useCCTPBridge: true,
+ weight: 100,
},
{
chainId: EChain.Base,
@@ -307,6 +313,7 @@ const SEED_ROWS: readonly ISeedRow[] = [
name: "USD Coin",
decimals: 6,
useCCTPBridge: true,
+ weight: 100,
},
// Sepolia (11155111)
{
@@ -318,6 +325,7 @@ const SEED_ROWS: readonly ISeedRow[] = [
name: "USD Coin",
decimals: 6,
useCCTPBridge: true,
+ weight: 100,
},
];
diff --git a/src/lib/implementations/utils/SupportedChainsBlockchainProvider.ts b/src/lib/implementations/utils/SupportedChainsBlockchainProvider.ts
index 5e39e20..cc7902f 100644
--- a/src/lib/implementations/utils/SupportedChainsBlockchainProvider.ts
+++ b/src/lib/implementations/utils/SupportedChainsBlockchainProvider.ts
@@ -25,7 +25,7 @@ export class SupportedChainsBlockchainProvider implements IBlockchainProvider {
const viemChain = defineChain({
id: Number(BigInt(chain.chainId)),
name: chain.label,
- nativeCurrency: { name: "Ether", symbol: "ETH", decimals: 18 },
+ nativeCurrency: chain.nativeCurrency,
rpcUrls: {
default: { http: [chain.rpcUrl] },
},
diff --git a/src/lib/types/domain/KnownAsset.ts b/src/lib/types/domain/KnownAsset.ts
index 325960e..6525258 100644
--- a/src/lib/types/domain/KnownAsset.ts
+++ b/src/lib/types/domain/KnownAsset.ts
@@ -11,6 +11,8 @@ export class KnownAsset {
public readonly symbol: string,
public readonly decimals: number,
public readonly useCCTPBridge: boolean,
+ /** Higher weight sorts above peers in Balances defaults (e.g. stable > native). */
+ public readonly weight: number = 0,
public readonly iconUrl?: string,
) {}
}
diff --git a/src/lib/types/domain/SupportedChain.ts b/src/lib/types/domain/SupportedChain.ts
index 8e3f900..9c23f52 100644
--- a/src/lib/types/domain/SupportedChain.ts
+++ b/src/lib/types/domain/SupportedChain.ts
@@ -1,6 +1,13 @@
import type { OWSChainId } from "@1shotapi/ows-types";
import type { EChainNetworkType } from "../enum/EChainNetworkType";
+/** Native gas / payment currency for a catalog chain. */
+export interface INativeCurrency {
+ name: string;
+ symbol: string;
+ decimals: number;
+}
+
/**
* Catalog entry for a network the Branding Layer can switch to.
* `relayerUrl` is for future TX submission only — credentials/activity use
@@ -21,6 +28,7 @@ export class SupportedChain {
/** Base URL for tx/address explorer links (no trailing slash). */
public readonly blockExplorerUrl: string,
public readonly cctpBridgeDestination: boolean,
+ public readonly nativeCurrency: INativeCurrency,
/** Higher weight sorts above peers within the same network type. */
public readonly weight: number = 0,
) {}
diff --git a/src/lib/types/domain/TrackedAsset.ts b/src/lib/types/domain/TrackedAsset.ts
index 138e607..5ef2eb7 100644
--- a/src/lib/types/domain/TrackedAsset.ts
+++ b/src/lib/types/domain/TrackedAsset.ts
@@ -20,6 +20,8 @@ export class NewTrackedAsset {
public readonly decimals: number,
/** Optional host- or catalog-supplied HTTPS icon URL. */
public readonly iconUrl?: string,
+ /** Higher weight sorts above peers in Balances defaults. */
+ public readonly weight: number = 0,
) {}
static fromKnown(known: KnownAsset): NewTrackedAsset {
@@ -31,6 +33,7 @@ export class NewTrackedAsset {
known.symbol,
known.decimals,
known.iconUrl,
+ known.weight,
);
}
@@ -43,6 +46,7 @@ export class NewTrackedAsset {
this.symbol,
this.decimals,
iconUrl,
+ this.weight,
);
}
}
@@ -59,8 +63,9 @@ export class TrackedAsset extends NewTrackedAsset {
public readonly id: TrackedAssetId,
public balance: bigint | null,
iconUrl?: string,
+ weight: number = 0,
) {
- super(chainId, address, type, name, symbol, decimals, iconUrl);
+ super(chainId, address, type, name, symbol, decimals, iconUrl, weight);
}
static fromNew(
@@ -77,6 +82,7 @@ export class TrackedAsset extends NewTrackedAsset {
makeTrackedAssetId(asset.chainId, asset.address),
balance,
asset.iconUrl,
+ asset.weight,
);
}
@@ -91,6 +97,7 @@ export class TrackedAsset extends NewTrackedAsset {
this.id,
balance,
this.iconUrl,
+ this.weight,
);
}
}
diff --git a/src/lib/types/domain/index.ts b/src/lib/types/domain/index.ts
index d852e13..60b0d16 100644
--- a/src/lib/types/domain/index.ts
+++ b/src/lib/types/domain/index.ts
@@ -3,6 +3,7 @@ export { BitcoinUtxo } from "./BitcoinUtxo";
export { KnownAsset } from "./KnownAsset";
export { NewTrackedAsset, TrackedAsset } from "./TrackedAsset";
export { SupportedChain } from "./SupportedChain";
+export type { INativeCurrency } from "./SupportedChain";
export type {
IDelegationCaveat,
IDelegationSummary,
diff --git a/src/lib/types/enum/EAssetType.ts b/src/lib/types/enum/EAssetType.ts
index 0950def..2bb28ce 100644
--- a/src/lib/types/enum/EAssetType.ts
+++ b/src/lib/types/enum/EAssetType.ts
@@ -1,5 +1,6 @@
-/** On-chain asset standard. Only ERC-20 balances are fetched today. */
+/** On-chain asset standard. ERC-20 and Native balances are fetched today. */
export enum EAssetType {
+ Native = "native",
Erc20 = "erc20",
Erc721 = "erc721",
Erc1155 = "erc1155",
diff --git a/test/lib/implementations/business/utils/CCTPUtils.test.ts b/test/lib/implementations/business/utils/CCTPUtils.test.ts
index 4569737..373977c 100644
--- a/test/lib/implementations/business/utils/CCTPUtils.test.ts
+++ b/test/lib/implementations/business/utils/CCTPUtils.test.ts
@@ -37,6 +37,7 @@ function chain(
String(id),
"https://explorer.example",
dest,
+ { name: "Ether", symbol: "ETH", decimals: 18 },
);
}