@andrewkimjoseph/celina-sdk 0.9.8 → 0.9.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/src/a2a/agent-card.d.ts +37 -0
- package/build/src/a2a/agent-card.js +46 -0
- package/build/src/a2a/agent-card.js.map +1 -0
- package/build/src/a2a/index.d.ts +2 -0
- package/build/src/a2a/index.js +3 -0
- package/build/src/a2a/index.js.map +1 -0
- package/build/src/a2a/skills.d.ts +18 -0
- package/build/src/a2a/skills.js +101 -0
- package/build/src/a2a/skills.js.map +1 -0
- package/build/src/abis/aave-pool.d.ts +37 -0
- package/build/src/abis/aave-pool.js +26 -0
- package/build/src/abis/aave-pool.js.map +1 -0
- package/build/src/abis/accounts.d.ts +13 -0
- package/build/src/abis/accounts.js +10 -0
- package/build/src/abis/accounts.js.map +1 -0
- package/build/src/abis/election.d.ts +124 -0
- package/build/src/abis/election.js +88 -0
- package/build/src/abis/election.js.map +1 -0
- package/build/src/abis/gooddollar-broker.d.ts +77 -0
- package/build/src/abis/gooddollar-broker.js +44 -0
- package/build/src/abis/gooddollar-broker.js.map +1 -0
- package/build/src/abis/gooddollar-identity.d.ts +85 -0
- package/build/src/abis/gooddollar-identity.js +52 -0
- package/build/src/abis/gooddollar-identity.js.map +1 -0
- package/build/src/abis/governance.d.ts +86 -0
- package/build/src/abis/governance.js +68 -0
- package/build/src/abis/governance.js.map +1 -0
- package/build/src/abis/locked-gold.d.ts +10 -0
- package/build/src/abis/locked-gold.js +10 -0
- package/build/src/abis/locked-gold.js.map +1 -0
- package/build/src/abis/nft.d.ts +107 -0
- package/build/src/abis/nft.js +75 -0
- package/build/src/abis/nft.js.map +1 -0
- package/build/src/abis/permit2.d.ts +43 -0
- package/build/src/abis/permit2.js +30 -0
- package/build/src/abis/permit2.js.map +1 -0
- package/build/src/abis/self-registry.d.ts +194 -0
- package/build/src/abis/self-registry.js +120 -0
- package/build/src/abis/self-registry.js.map +1 -0
- package/build/src/abis/ubi-scheme.d.ts +91 -0
- package/build/src/abis/ubi-scheme.js +66 -0
- package/build/src/abis/ubi-scheme.js.map +1 -0
- package/build/src/abis/uniswap-state-view.d.ts +34 -0
- package/build/src/abis/uniswap-state-view.js +22 -0
- package/build/src/abis/uniswap-state-view.js.map +1 -0
- package/build/src/abis/uniswap-v4-quoter.d.ts +86 -0
- package/build/src/abis/uniswap-v4-quoter.js +64 -0
- package/build/src/abis/uniswap-v4-quoter.js.map +1 -0
- package/build/src/abis/universal-router.d.ts +16 -0
- package/build/src/abis/universal-router.js +14 -0
- package/build/src/abis/universal-router.js.map +1 -0
- package/build/src/abis/validators-minimal.d.ts +65 -0
- package/build/src/abis/validators-minimal.js +39 -0
- package/build/src/abis/validators-minimal.js.map +1 -0
- package/build/src/analytics/amplitude.d.ts +11 -0
- package/build/src/analytics/amplitude.js +76 -0
- package/build/src/analytics/amplitude.js.map +1 -0
- package/build/src/analytics/config.d.ts +7 -0
- package/build/src/analytics/config.js +28 -0
- package/build/src/analytics/config.js.map +1 -0
- package/build/src/analytics/consumer-package.d.ts +9 -0
- package/build/src/analytics/consumer-package.js +143 -0
- package/build/src/analytics/consumer-package.js.map +1 -0
- package/build/src/analytics/mcp-tool-events.d.ts +5 -0
- package/build/src/analytics/mcp-tool-events.js +53 -0
- package/build/src/analytics/mcp-tool-events.js.map +1 -0
- package/build/src/analytics/wallet-context.d.ts +11 -0
- package/build/src/analytics/wallet-context.js +81 -0
- package/build/src/analytics/wallet-context.js.map +1 -0
- package/build/src/analytics/wallet-extract.d.ts +9 -0
- package/build/src/analytics/wallet-extract.js +21 -0
- package/build/src/analytics/wallet-extract.js.map +1 -0
- package/build/src/analytics/wrap-service.d.ts +5 -0
- package/build/src/analytics/wrap-service.js +38 -0
- package/build/src/analytics/wrap-service.js.map +1 -0
- package/build/src/clients/celo-client.d.ts +17 -0
- package/build/src/clients/celo-client.js +28 -0
- package/build/src/clients/celo-client.js.map +1 -0
- package/build/src/clients/ens-client.d.ts +17 -0
- package/build/src/clients/ens-client.js +30 -0
- package/build/src/clients/ens-client.js.map +1 -0
- package/build/src/clients/mento-sdk.d.ts +2 -0
- package/build/src/clients/mento-sdk.js +9 -0
- package/build/src/clients/mento-sdk.js.map +1 -0
- package/build/src/clients/self-api.d.ts +82 -0
- package/build/src/clients/self-api.js +242 -0
- package/build/src/clients/self-api.js.map +1 -0
- package/build/src/clients/uniswap-sdk.d.ts +4 -0
- package/build/src/clients/uniswap-sdk.js +13 -0
- package/build/src/clients/uniswap-sdk.js.map +1 -0
- package/build/src/config/aave.d.ts +17 -0
- package/build/src/config/aave.js +77 -0
- package/build/src/config/aave.js.map +1 -0
- package/build/src/config/celina-tag.d.ts +4 -0
- package/build/src/config/celina-tag.js +13 -0
- package/build/src/config/celina-tag.js.map +1 -0
- package/build/src/config/celo-core-contracts.d.ts +8 -0
- package/build/src/config/celo-core-contracts.js +9 -0
- package/build/src/config/celo-core-contracts.js.map +1 -0
- package/build/src/config/chains.d.ts +937 -0
- package/build/src/config/chains.js +319 -0
- package/build/src/config/chains.js.map +1 -0
- package/build/src/config/gooddollar.d.ts +16 -0
- package/build/src/config/gooddollar.js +24 -0
- package/build/src/config/gooddollar.js.map +1 -0
- package/build/src/config/sdk-config.d.ts +33 -0
- package/build/src/config/sdk-config.js +31 -0
- package/build/src/config/sdk-config.js.map +1 -0
- package/build/src/config/self.d.ts +22 -0
- package/build/src/config/self.js +27 -0
- package/build/src/config/self.js.map +1 -0
- package/build/src/config/uniswap.d.ts +42 -0
- package/build/src/config/uniswap.js +76 -0
- package/build/src/config/uniswap.js.map +1 -0
- package/build/src/index.d.ts +90 -0
- package/build/src/index.js +65 -0
- package/build/src/index.js.map +1 -0
- package/build/src/oasf/index.d.ts +2 -0
- package/build/src/oasf/index.js +3 -0
- package/build/src/oasf/index.js.map +1 -0
- package/build/src/oasf/record.d.ts +39 -0
- package/build/src/oasf/record.js +35 -0
- package/build/src/oasf/record.js.map +1 -0
- package/build/src/oasf/taxonomy.d.ts +19 -0
- package/build/src/oasf/taxonomy.js +46 -0
- package/build/src/oasf/taxonomy.js.map +1 -0
- package/build/src/services/aave.service.d.ts +58 -0
- package/build/src/services/aave.service.js +210 -0
- package/build/src/services/aave.service.js.map +1 -0
- package/build/src/services/account.service.d.ts +22 -0
- package/build/src/services/account.service.js +29 -0
- package/build/src/services/account.service.js.map +1 -0
- package/build/src/services/blockchain.service.d.ts +107 -0
- package/build/src/services/blockchain.service.js +151 -0
- package/build/src/services/blockchain.service.js.map +1 -0
- package/build/src/services/contract.service.d.ts +78 -0
- package/build/src/services/contract.service.js +117 -0
- package/build/src/services/contract.service.js.map +1 -0
- package/build/src/services/ens.service.d.ts +44 -0
- package/build/src/services/ens.service.js +92 -0
- package/build/src/services/ens.service.js.map +1 -0
- package/build/src/services/gooddollar.service.d.ts +183 -0
- package/build/src/services/gooddollar.service.js +675 -0
- package/build/src/services/gooddollar.service.js.map +1 -0
- package/build/src/services/governance.service.d.ts +96 -0
- package/build/src/services/governance.service.js +255 -0
- package/build/src/services/governance.service.js.map +1 -0
- package/build/src/services/mento-fx.service.d.ts +80 -0
- package/build/src/services/mento-fx.service.js +319 -0
- package/build/src/services/mento-fx.service.js.map +1 -0
- package/build/src/services/nft.service.d.ts +58 -0
- package/build/src/services/nft.service.js +222 -0
- package/build/src/services/nft.service.js.map +1 -0
- package/build/src/services/self-session-store.d.ts +19 -0
- package/build/src/services/self-session-store.js +28 -0
- package/build/src/services/self-session-store.js.map +1 -0
- package/build/src/services/self.service.d.ts +241 -0
- package/build/src/services/self.service.js +699 -0
- package/build/src/services/self.service.js.map +1 -0
- package/build/src/services/staking.service.d.ts +140 -0
- package/build/src/services/staking.service.js +444 -0
- package/build/src/services/staking.service.js.map +1 -0
- package/build/src/services/token.service.d.ts +110 -0
- package/build/src/services/token.service.js +189 -0
- package/build/src/services/token.service.js.map +1 -0
- package/build/src/services/transaction.service.d.ts +68 -0
- package/build/src/services/transaction.service.js +198 -0
- package/build/src/services/transaction.service.js.map +1 -0
- package/build/src/services/uniswap-path-router.d.ts +40 -0
- package/build/src/services/uniswap-path-router.js +168 -0
- package/build/src/services/uniswap-path-router.js.map +1 -0
- package/build/src/services/uniswap-pool-discovery.d.ts +55 -0
- package/build/src/services/uniswap-pool-discovery.js +198 -0
- package/build/src/services/uniswap-pool-discovery.js.map +1 -0
- package/build/src/services/uniswap.service.d.ts +82 -0
- package/build/src/services/uniswap.service.js +352 -0
- package/build/src/services/uniswap.service.js.map +1 -0
- package/build/src/simulation/index.d.ts +5 -0
- package/build/src/simulation/index.js +2 -0
- package/build/src/simulation/index.js.map +1 -0
- package/build/src/simulation/simulate-prepared-step.d.ts +17 -0
- package/build/src/simulation/simulate-prepared-step.js +42 -0
- package/build/src/simulation/simulate-prepared-step.js.map +1 -0
- package/build/src/tools/catalog.d.ts +11 -0
- package/build/src/tools/catalog.js +43 -0
- package/build/src/tools/catalog.js.map +1 -0
- package/build/src/tools/domains/aave.d.ts +2 -0
- package/build/src/tools/domains/aave.js +115 -0
- package/build/src/tools/domains/aave.js.map +1 -0
- package/build/src/tools/domains/blockchain.d.ts +2 -0
- package/build/src/tools/domains/blockchain.js +86 -0
- package/build/src/tools/domains/blockchain.js.map +1 -0
- package/build/src/tools/domains/browser.d.ts +2 -0
- package/build/src/tools/domains/browser.js +45 -0
- package/build/src/tools/domains/browser.js.map +1 -0
- package/build/src/tools/domains/contract.d.ts +2 -0
- package/build/src/tools/domains/contract.js +67 -0
- package/build/src/tools/domains/contract.js.map +1 -0
- package/build/src/tools/domains/ens.d.ts +2 -0
- package/build/src/tools/domains/ens.js +16 -0
- package/build/src/tools/domains/ens.js.map +1 -0
- package/build/src/tools/domains/gooddollar.d.ts +2 -0
- package/build/src/tools/domains/gooddollar.js +171 -0
- package/build/src/tools/domains/gooddollar.js.map +1 -0
- package/build/src/tools/domains/governance.d.ts +2 -0
- package/build/src/tools/domains/governance.js +41 -0
- package/build/src/tools/domains/governance.js.map +1 -0
- package/build/src/tools/domains/index.d.ts +1 -0
- package/build/src/tools/domains/index.js +31 -0
- package/build/src/tools/domains/index.js.map +1 -0
- package/build/src/tools/domains/mento-fx.d.ts +2 -0
- package/build/src/tools/domains/mento-fx.js +67 -0
- package/build/src/tools/domains/mento-fx.js.map +1 -0
- package/build/src/tools/domains/nft.d.ts +2 -0
- package/build/src/tools/domains/nft.js +38 -0
- package/build/src/tools/domains/nft.js.map +1 -0
- package/build/src/tools/domains/self.d.ts +2 -0
- package/build/src/tools/domains/self.js +187 -0
- package/build/src/tools/domains/self.js.map +1 -0
- package/build/src/tools/domains/staking.d.ts +2 -0
- package/build/src/tools/domains/staking.js +74 -0
- package/build/src/tools/domains/staking.js.map +1 -0
- package/build/src/tools/domains/token.d.ts +2 -0
- package/build/src/tools/domains/token.js +74 -0
- package/build/src/tools/domains/token.js.map +1 -0
- package/build/src/tools/domains/transaction.d.ts +2 -0
- package/build/src/tools/domains/transaction.js +120 -0
- package/build/src/tools/domains/transaction.js.map +1 -0
- package/build/src/tools/domains/uniswap.d.ts +2 -0
- package/build/src/tools/domains/uniswap.js +67 -0
- package/build/src/tools/domains/uniswap.js.map +1 -0
- package/build/src/tools/filter.d.ts +2 -0
- package/build/src/tools/filter.js +50 -0
- package/build/src/tools/filter.js.map +1 -0
- package/build/src/tools/index.d.ts +7 -0
- package/build/src/tools/index.js +7 -0
- package/build/src/tools/index.js.map +1 -0
- package/build/src/tools/schemas/common.d.ts +165 -0
- package/build/src/tools/schemas/common.js +207 -0
- package/build/src/tools/schemas/common.js.map +1 -0
- package/build/src/tools/schemas/wallet-params.d.ts +9 -0
- package/build/src/tools/schemas/wallet-params.js +52 -0
- package/build/src/tools/schemas/wallet-params.js.map +1 -0
- package/build/src/tools/swap-routing.d.ts +25 -0
- package/build/src/tools/swap-routing.js +174 -0
- package/build/src/tools/swap-routing.js.map +1 -0
- package/build/src/tools/types.d.ts +124 -0
- package/build/src/tools/types.js +2 -0
- package/build/src/tools/types.js.map +1 -0
- package/build/src/tools/utils/normalize-token.d.ts +2 -0
- package/build/src/tools/utils/normalize-token.js +12 -0
- package/build/src/tools/utils/normalize-token.js.map +1 -0
- package/build/src/tools/utils/wallet.d.ts +4 -0
- package/build/src/tools/utils/wallet.js +8 -0
- package/build/src/tools/utils/wallet.js.map +1 -0
- package/build/src/tools/website-sync.d.ts +28 -0
- package/build/src/tools/website-sync.js +165 -0
- package/build/src/tools/website-sync.js.map +1 -0
- package/build/src/types/prepared.d.ts +28 -0
- package/build/src/types/prepared.js +12 -0
- package/build/src/types/prepared.js.map +1 -0
- package/build/src/utils/celo-format.d.ts +6 -0
- package/build/src/utils/celo-format.js +17 -0
- package/build/src/utils/celo-format.js.map +1 -0
- package/build/src/utils/erc20-allowance-storage.d.ts +20 -0
- package/build/src/utils/erc20-allowance-storage.js +64 -0
- package/build/src/utils/erc20-allowance-storage.js.map +1 -0
- package/build/src/utils/format-date.d.ts +2 -0
- package/build/src/utils/format-date.js +13 -0
- package/build/src/utils/format-date.js.map +1 -0
- package/build/src/utils/format-duration.d.ts +2 -0
- package/build/src/utils/format-duration.js +17 -0
- package/build/src/utils/format-duration.js.map +1 -0
- package/build/src/utils/format-unix-datetime.d.ts +4 -0
- package/build/src/utils/format-unix-datetime.js +18 -0
- package/build/src/utils/format-unix-datetime.js.map +1 -0
- package/build/src/utils/gooddollar-ubi-period.d.ts +23 -0
- package/build/src/utils/gooddollar-ubi-period.js +23 -0
- package/build/src/utils/gooddollar-ubi-period.js.map +1 -0
- package/build/src/utils/normalize-address.d.ts +7 -0
- package/build/src/utils/normalize-address.js +16 -0
- package/build/src/utils/normalize-address.js.map +1 -0
- package/build/src/utils/self-format.d.ts +28 -0
- package/build/src/utils/self-format.js +79 -0
- package/build/src/utils/self-format.js.map +1 -0
- package/build/src/utils/self-signing.d.ts +4 -0
- package/build/src/utils/self-signing.js +38 -0
- package/build/src/utils/self-signing.js.map +1 -0
- package/build/src/utils/transaction-errors.d.ts +3 -0
- package/build/src/utils/transaction-errors.js +17 -0
- package/build/src/utils/transaction-errors.js.map +1 -0
- package/build/tests/catalog/domains/blockchain.d.ts +2 -0
- package/build/tests/catalog/domains/blockchain.js +127 -0
- package/build/tests/catalog/domains/blockchain.js.map +1 -0
- package/build/tests/catalog/domains/chain-ext.d.ts +5 -0
- package/build/tests/catalog/domains/chain-ext.js +207 -0
- package/build/tests/catalog/domains/chain-ext.js.map +1 -0
- package/build/tests/catalog/domains/defi.d.ts +6 -0
- package/build/tests/catalog/domains/defi.js +581 -0
- package/build/tests/catalog/domains/defi.js.map +1 -0
- package/build/tests/catalog/domains/self.d.ts +2 -0
- package/build/tests/catalog/domains/self.js +208 -0
- package/build/tests/catalog/domains/self.js.map +1 -0
- package/build/tests/catalog/domains/token.d.ts +2 -0
- package/build/tests/catalog/domains/token.js +70 -0
- package/build/tests/catalog/domains/token.js.map +1 -0
- package/build/tests/catalog/domains/transaction.d.ts +2 -0
- package/build/tests/catalog/domains/transaction.js +96 -0
- package/build/tests/catalog/domains/transaction.js.map +1 -0
- package/build/tests/catalog/index.d.ts +2 -0
- package/build/tests/catalog/index.js +2 -0
- package/build/tests/catalog/index.js.map +1 -0
- package/build/tests/catalog/operations.d.ts +12 -0
- package/build/tests/catalog/operations.js +29 -0
- package/build/tests/catalog/operations.js.map +1 -0
- package/build/tests/catalog/types.d.ts +24 -0
- package/build/tests/catalog/types.js +2 -0
- package/build/tests/catalog/types.js.map +1 -0
- package/build/tests/fixtures/mainnet.d.ts +54 -0
- package/build/tests/fixtures/mainnet.js +53 -0
- package/build/tests/fixtures/mainnet.js.map +1 -0
- package/build/tests/helpers/assert.d.ts +4 -0
- package/build/tests/helpers/assert.js +24 -0
- package/build/tests/helpers/assert.js.map +1 -0
- package/build/tests/helpers/env.d.ts +11 -0
- package/build/tests/helpers/env.js +28 -0
- package/build/tests/helpers/env.js.map +1 -0
- package/build/tests/helpers/gating.d.ts +3 -0
- package/build/tests/helpers/gating.js +23 -0
- package/build/tests/helpers/gating.js.map +1 -0
- package/build/tests/testing-entry.d.ts +6 -0
- package/build/tests/testing-entry.js +6 -0
- package/build/tests/testing-entry.js.map +1 -0
- package/package.json +5 -9
- package/tests/README.md +0 -78
- package/tests/catalog/domains/blockchain.ts +0 -133
- package/tests/catalog/domains/chain-ext.ts +0 -219
- package/tests/catalog/domains/defi.ts +0 -647
- package/tests/catalog/domains/self.ts +0 -220
- package/tests/catalog/domains/token.ts +0 -74
- package/tests/catalog/domains/transaction.ts +0 -111
- package/tests/catalog/index.ts +0 -7
- package/tests/catalog/operations.ts +0 -53
- package/tests/catalog/types.ts +0 -27
- package/tests/fixtures/mainnet.ts +0 -93
- package/tests/helpers/assert.ts +0 -30
- package/tests/helpers/env.ts +0 -38
- package/tests/helpers/gating.ts +0 -36
- package/tests/testing-entry.ts +0 -27
|
@@ -0,0 +1,319 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Mento FX: getFxQuote is read-only; prepareFx builds approve + swap steps when needed.
|
|
3
|
+
* Uses @mento-protocol/mento-sdk for routing and simulates allowance via state overrides.
|
|
4
|
+
*/
|
|
5
|
+
import { concat, decodeFunctionData, erc20Abi, formatUnits, } from "viem";
|
|
6
|
+
import { ChainId, deadlineFromMinutes, Mento, RouteNotFoundError, FXMarketClosedError, } from "../clients/mento-sdk.js";
|
|
7
|
+
import { CELINA_DATA_SUFFIX } from "../config/celina-tag.js";
|
|
8
|
+
import { toMentoTokenAddress } from "../config/chains.js";
|
|
9
|
+
import { ALLOWANCE_MAPPING_SLOTS, erc20AllowanceStateOverride, isLikelyTransferFailed, } from "../utils/erc20-allowance-storage.js";
|
|
10
|
+
import { serializePreparedFlow, } from "../types/prepared.js";
|
|
11
|
+
import { TokenService } from "./token.service.js";
|
|
12
|
+
const DEFAULT_SLIPPAGE = 0.5;
|
|
13
|
+
const DEFAULT_DEADLINE_MINUTES = 5;
|
|
14
|
+
function trimDisplayDecimals(value) {
|
|
15
|
+
const num = Number(value);
|
|
16
|
+
if (!Number.isFinite(num)) {
|
|
17
|
+
return value;
|
|
18
|
+
}
|
|
19
|
+
if (Math.abs(num) >= 1000) {
|
|
20
|
+
return num.toLocaleString(undefined, { maximumFractionDigits: 2 });
|
|
21
|
+
}
|
|
22
|
+
if (Math.abs(num) >= 1) {
|
|
23
|
+
return num.toLocaleString(undefined, { maximumFractionDigits: 4 });
|
|
24
|
+
}
|
|
25
|
+
return num.toLocaleString(undefined, { maximumSignificantDigits: 6 });
|
|
26
|
+
}
|
|
27
|
+
/** Human-friendly amount for UI labels (handles raw base-unit integers). */
|
|
28
|
+
export function formatDisplayAmount(amount, decimals) {
|
|
29
|
+
const trimmed = amount.trim();
|
|
30
|
+
const approx = trimmed.startsWith("~");
|
|
31
|
+
let numeric = approx ? trimmed.slice(1).trim() : trimmed;
|
|
32
|
+
numeric = numeric.replace(/,/g, "");
|
|
33
|
+
const integerPart = numeric.split(".")[0] ?? numeric;
|
|
34
|
+
if (/^\d+(?:\.\d+)?$/.test(numeric) && integerPart.length >= 10) {
|
|
35
|
+
try {
|
|
36
|
+
const human = formatUnits(BigInt(integerPart), decimals);
|
|
37
|
+
const asNumber = Number(human);
|
|
38
|
+
if (Number.isFinite(asNumber) && asNumber >= 0 && asNumber < 1_000_000_000) {
|
|
39
|
+
numeric = trimDisplayDecimals(human);
|
|
40
|
+
return approx ? `~${numeric}` : numeric;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
catch {
|
|
44
|
+
// fall through
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
if (/^\d+(?:\.\d+)?$/.test(numeric)) {
|
|
48
|
+
numeric = trimDisplayDecimals(numeric);
|
|
49
|
+
}
|
|
50
|
+
return approx ? `~${numeric}` : numeric;
|
|
51
|
+
}
|
|
52
|
+
function parseErc20Approve(params) {
|
|
53
|
+
try {
|
|
54
|
+
const decoded = decodeFunctionData({
|
|
55
|
+
abi: erc20Abi,
|
|
56
|
+
data: params.data,
|
|
57
|
+
});
|
|
58
|
+
if (decoded.functionName !== "approve") {
|
|
59
|
+
return null;
|
|
60
|
+
}
|
|
61
|
+
return {
|
|
62
|
+
token: params.to,
|
|
63
|
+
spender: decoded.args[0],
|
|
64
|
+
amount: decoded.args[1],
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
catch {
|
|
68
|
+
return null;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
function taggedCalldata(data) {
|
|
72
|
+
return concat([data, CELINA_DATA_SUFFIX]);
|
|
73
|
+
}
|
|
74
|
+
function callParamsToPreparedTx(params, description) {
|
|
75
|
+
const approve = parseErc20Approve(params);
|
|
76
|
+
if (approve) {
|
|
77
|
+
return {
|
|
78
|
+
kind: "erc20",
|
|
79
|
+
to: approve.token,
|
|
80
|
+
data: taggedCalldata(params.data),
|
|
81
|
+
value: "0",
|
|
82
|
+
description,
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
return {
|
|
86
|
+
kind: "contract",
|
|
87
|
+
to: params.to,
|
|
88
|
+
data: taggedCalldata(params.data),
|
|
89
|
+
value: BigInt(params.value).toString(),
|
|
90
|
+
description,
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
/** Mento FX quotes, gas estimates, and `prepareFx` flows on Celo mainnet. */
|
|
94
|
+
export class MentoFxService {
|
|
95
|
+
clientFactory;
|
|
96
|
+
tokenService;
|
|
97
|
+
constructor(clientFactory) {
|
|
98
|
+
this.clientFactory = clientFactory;
|
|
99
|
+
this.tokenService = new TokenService(clientFactory);
|
|
100
|
+
}
|
|
101
|
+
async getMentoClient(publicClient) {
|
|
102
|
+
return Mento.create(ChainId.CELO, publicClient);
|
|
103
|
+
}
|
|
104
|
+
resolveMentoPair(tokenIn, tokenOut) {
|
|
105
|
+
const resolvedIn = this.tokenService.resolveToken(tokenIn);
|
|
106
|
+
const resolvedOut = this.tokenService.resolveToken(tokenOut);
|
|
107
|
+
return {
|
|
108
|
+
resolvedIn,
|
|
109
|
+
resolvedOut,
|
|
110
|
+
mentoIn: toMentoTokenAddress(resolvedIn.address),
|
|
111
|
+
mentoOut: toMentoTokenAddress(resolvedOut.address),
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
fxOptions(params) {
|
|
115
|
+
const slippageTolerance = params?.slippageTolerance ?? DEFAULT_SLIPPAGE;
|
|
116
|
+
const deadlineMinutes = params?.deadlineMinutes ?? DEFAULT_DEADLINE_MINUTES;
|
|
117
|
+
return {
|
|
118
|
+
slippageTolerance,
|
|
119
|
+
deadlineMinutes,
|
|
120
|
+
deadline: deadlineFromMinutes(deadlineMinutes),
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
formatFxError(error, tokenIn, tokenOut) {
|
|
124
|
+
if (error instanceof RouteNotFoundError) {
|
|
125
|
+
throw new Error(`No Mento FX route for ${tokenIn} → ${tokenOut}.`);
|
|
126
|
+
}
|
|
127
|
+
if (error instanceof FXMarketClosedError) {
|
|
128
|
+
throw new Error("Mento FX market is currently closed. FX quotes and execution are unavailable until the market reopens.");
|
|
129
|
+
}
|
|
130
|
+
if (error instanceof Error && /FXMarketClosed/i.test(error.message)) {
|
|
131
|
+
throw new Error("Mento FX market is currently closed. FX quotes and execution are unavailable until the market reopens.");
|
|
132
|
+
}
|
|
133
|
+
throw error instanceof Error ? error : new Error(String(error));
|
|
134
|
+
}
|
|
135
|
+
async buildFxSwap(from, tokenIn, tokenOut, amount, params) {
|
|
136
|
+
const { public: client } = this.clientFactory.getClients();
|
|
137
|
+
const { resolvedIn, resolvedOut, mentoIn, mentoOut } = this.resolveMentoPair(tokenIn, tokenOut);
|
|
138
|
+
const recipient = params?.recipient ?? from;
|
|
139
|
+
const amountInWei = this.tokenService.parseAmount(amount, resolvedIn.decimals);
|
|
140
|
+
const { slippageTolerance, deadlineMinutes, deadline } = this.fxOptions(params);
|
|
141
|
+
await this.tokenService.assertSpendableBalance(from, resolvedIn, amount, {
|
|
142
|
+
spendToken: resolvedIn.address === "native" ? mentoIn : resolvedIn.address,
|
|
143
|
+
});
|
|
144
|
+
const mento = await this.getMentoClient(client);
|
|
145
|
+
const { approval, swap } = await mento.swap.buildSwapTransaction(mentoIn, mentoOut, amountInWei, recipient, from, { slippageTolerance, deadline });
|
|
146
|
+
return {
|
|
147
|
+
client,
|
|
148
|
+
from,
|
|
149
|
+
recipient,
|
|
150
|
+
resolvedIn,
|
|
151
|
+
resolvedOut,
|
|
152
|
+
amount,
|
|
153
|
+
approval,
|
|
154
|
+
swap,
|
|
155
|
+
slippageTolerance,
|
|
156
|
+
deadlineMinutes,
|
|
157
|
+
deadline,
|
|
158
|
+
};
|
|
159
|
+
}
|
|
160
|
+
async estimateCallGas(client, from, params) {
|
|
161
|
+
const approve = parseErc20Approve(params);
|
|
162
|
+
if (approve) {
|
|
163
|
+
const gas = await client.estimateContractGas({
|
|
164
|
+
account: from,
|
|
165
|
+
address: approve.token,
|
|
166
|
+
abi: erc20Abi,
|
|
167
|
+
functionName: "approve",
|
|
168
|
+
args: [approve.spender, approve.amount],
|
|
169
|
+
});
|
|
170
|
+
return gas.toString();
|
|
171
|
+
}
|
|
172
|
+
const gas = await client.estimateGas({
|
|
173
|
+
account: from,
|
|
174
|
+
to: params.to,
|
|
175
|
+
data: params.data,
|
|
176
|
+
value: BigInt(params.value),
|
|
177
|
+
});
|
|
178
|
+
return gas.toString();
|
|
179
|
+
}
|
|
180
|
+
async estimateSwapGasWithAllowance(client, from, params, approve) {
|
|
181
|
+
const request = {
|
|
182
|
+
account: from,
|
|
183
|
+
to: params.to,
|
|
184
|
+
data: params.data,
|
|
185
|
+
value: BigInt(params.value),
|
|
186
|
+
};
|
|
187
|
+
for (const mappingSlot of ALLOWANCE_MAPPING_SLOTS) {
|
|
188
|
+
try {
|
|
189
|
+
const gas = await client.estimateGas({
|
|
190
|
+
...request,
|
|
191
|
+
stateOverride: erc20AllowanceStateOverride(approve.token, from, approve.spender, approve.amount, mappingSlot),
|
|
192
|
+
});
|
|
193
|
+
return gas.toString();
|
|
194
|
+
}
|
|
195
|
+
catch (error) {
|
|
196
|
+
if (!isLikelyTransferFailed(error)) {
|
|
197
|
+
throw error;
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
throw new Error("Could not estimate Mento FX swap gas: failed to simulate ERC-20 allowance for this token.");
|
|
202
|
+
}
|
|
203
|
+
baseQuoteFields(resolvedIn, resolvedOut, amount, expectedOutWei, routeHops) {
|
|
204
|
+
return {
|
|
205
|
+
protocol: "mento_fx",
|
|
206
|
+
network: "mainnet",
|
|
207
|
+
tokenIn: resolvedIn.symbol,
|
|
208
|
+
tokenOut: resolvedOut.symbol,
|
|
209
|
+
amountIn: amount,
|
|
210
|
+
expectedOut: formatUnits(expectedOutWei, resolvedOut.decimals),
|
|
211
|
+
routeHops,
|
|
212
|
+
};
|
|
213
|
+
}
|
|
214
|
+
/**
|
|
215
|
+
* Expected Mento FX output for a token pair — no wallet required.
|
|
216
|
+
* @param tokenIn - Input token symbol or address
|
|
217
|
+
* @param tokenOut - Output token symbol or address
|
|
218
|
+
* @param amount - Human-readable input amount
|
|
219
|
+
* @param _from - Deprecated; ignored. Balance checks run on prepare/estimate only.
|
|
220
|
+
*/
|
|
221
|
+
async getFxQuote(tokenIn, tokenOut, amount, _from) {
|
|
222
|
+
const { public: client } = this.clientFactory.getClients();
|
|
223
|
+
const { resolvedIn, resolvedOut, mentoIn, mentoOut } = this.resolveMentoPair(tokenIn, tokenOut);
|
|
224
|
+
const amountInWei = this.tokenService.parseAmount(amount, resolvedIn.decimals);
|
|
225
|
+
try {
|
|
226
|
+
const mento = await this.getMentoClient(client);
|
|
227
|
+
const [expectedOutWei, route] = await Promise.all([
|
|
228
|
+
mento.quotes.getAmountOut(mentoIn, mentoOut, amountInWei),
|
|
229
|
+
mento.routes.findRoute(mentoIn, mentoOut),
|
|
230
|
+
]);
|
|
231
|
+
return this.baseQuoteFields(resolvedIn, resolvedOut, amount, expectedOutWei, route.path.length);
|
|
232
|
+
}
|
|
233
|
+
catch (error) {
|
|
234
|
+
this.formatFxError(error, resolvedIn.symbol, resolvedOut.symbol);
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
/**
|
|
238
|
+
* Simulate gas for a Mento FX swap from `from`, including approval if needed.
|
|
239
|
+
* @param from - Sender wallet address
|
|
240
|
+
* @param tokenIn - Input token symbol or address
|
|
241
|
+
* @param tokenOut - Output token symbol or address
|
|
242
|
+
* @param amount - Human-readable input amount
|
|
243
|
+
* @param params - Optional slippage, deadline, and recipient
|
|
244
|
+
*/
|
|
245
|
+
async estimateFx(from, tokenIn, tokenOut, amount, params) {
|
|
246
|
+
try {
|
|
247
|
+
const built = await this.buildFxSwap(from, tokenIn, tokenOut, amount, params);
|
|
248
|
+
const { client, resolvedIn, resolvedOut, approval, swap, recipient, slippageTolerance, deadlineMinutes, deadline, } = built;
|
|
249
|
+
const approvalParsed = approval ? parseErc20Approve(approval) : null;
|
|
250
|
+
const approvalGas = approval
|
|
251
|
+
? await this.estimateCallGas(client, from, approval)
|
|
252
|
+
: undefined;
|
|
253
|
+
let fxGas;
|
|
254
|
+
let swapGasEstimated = true;
|
|
255
|
+
try {
|
|
256
|
+
fxGas =
|
|
257
|
+
approvalParsed !== null
|
|
258
|
+
? await this.estimateSwapGasWithAllowance(client, from, swap.params, approvalParsed)
|
|
259
|
+
: await this.estimateCallGas(client, from, swap.params);
|
|
260
|
+
}
|
|
261
|
+
catch (error) {
|
|
262
|
+
// USDT and other proxy/non-standard ERC-20s often cannot be simulated pre-approval.
|
|
263
|
+
if (approvalParsed === null) {
|
|
264
|
+
throw error;
|
|
265
|
+
}
|
|
266
|
+
swapGasEstimated = false;
|
|
267
|
+
}
|
|
268
|
+
return {
|
|
269
|
+
...this.baseQuoteFields(resolvedIn, resolvedOut, amount, swap.expectedAmountOut, swap.route.path.length),
|
|
270
|
+
from,
|
|
271
|
+
recipient,
|
|
272
|
+
amountOutMin: formatUnits(swap.amountOutMin, resolvedOut.decimals),
|
|
273
|
+
approvalNeeded: approval !== null,
|
|
274
|
+
approvalGas,
|
|
275
|
+
fxGas,
|
|
276
|
+
swapGasEstimated,
|
|
277
|
+
slippageTolerance,
|
|
278
|
+
deadline: deadline.toString(),
|
|
279
|
+
deadlineMinutes,
|
|
280
|
+
};
|
|
281
|
+
}
|
|
282
|
+
catch (error) {
|
|
283
|
+
this.formatFxError(error, tokenIn, tokenOut);
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
/**
|
|
287
|
+
* Build unsigned Mento FX steps (approve + swap when needed).
|
|
288
|
+
* @param from - Sender wallet address
|
|
289
|
+
* @param tokenIn - Input token symbol or address
|
|
290
|
+
* @param tokenOut - Output token symbol or address
|
|
291
|
+
* @param amount - Human-readable input amount
|
|
292
|
+
* @param params - Optional slippage, deadline, and recipient
|
|
293
|
+
* @returns 1–2 step `SerializedPreparedFlow` for sequential wallet signing
|
|
294
|
+
*/
|
|
295
|
+
async prepareFx(from, tokenIn, tokenOut, amount, params) {
|
|
296
|
+
try {
|
|
297
|
+
const built = await this.buildFxSwap(from, tokenIn, tokenOut, amount, params);
|
|
298
|
+
const { resolvedIn, resolvedOut, approval, swap, recipient } = built;
|
|
299
|
+
const displayIn = formatDisplayAmount(amount, resolvedIn.decimals);
|
|
300
|
+
const displayOut = formatDisplayAmount(formatUnits(swap.expectedAmountOut, resolvedOut.decimals), resolvedOut.decimals);
|
|
301
|
+
const steps = [];
|
|
302
|
+
if (approval) {
|
|
303
|
+
steps.push(callParamsToPreparedTx(approval, `Approve ${resolvedIn.symbol} for Mento FX`));
|
|
304
|
+
}
|
|
305
|
+
steps.push(callParamsToPreparedTx(swap.params, `Swap ${displayIn} ${resolvedIn.symbol} → ~${displayOut} ${resolvedOut.symbol}`));
|
|
306
|
+
const flow = {
|
|
307
|
+
network: "mainnet",
|
|
308
|
+
from,
|
|
309
|
+
summary: `Mento FX: ${displayIn} ${resolvedIn.symbol} → ${displayOut} ${resolvedOut.symbol}${recipient !== from ? ` (recipient ${recipient})` : ""}`,
|
|
310
|
+
steps,
|
|
311
|
+
};
|
|
312
|
+
return serializePreparedFlow(flow);
|
|
313
|
+
}
|
|
314
|
+
catch (error) {
|
|
315
|
+
this.formatFxError(error, tokenIn, tokenOut);
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
//# sourceMappingURL=mento-fx.service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mento-fx.service.js","sourceRoot":"","sources":["../../../src/services/mento-fx.service.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import type { CeloClientFactory } from "../clients/celo-client.js";
|
|
2
|
+
type NftStandard = "ERC721" | "ERC1155";
|
|
3
|
+
/** ERC-721 / ERC-1155 collection and balance reads with optional metadata fetch. */
|
|
4
|
+
export declare class NftService {
|
|
5
|
+
private readonly clientFactory;
|
|
6
|
+
constructor(clientFactory: CeloClientFactory);
|
|
7
|
+
private assertIsContract;
|
|
8
|
+
private detectStandard;
|
|
9
|
+
/**
|
|
10
|
+
* Collection and token metadata for an ERC-721 or ERC-1155 contract.
|
|
11
|
+
* @param contractAddress - NFT collection contract
|
|
12
|
+
* @param tokenId - Token id as decimal string
|
|
13
|
+
* @returns Standard, owner, collection info, and fetched JSON metadata when available
|
|
14
|
+
* @throws When the address is not a deployed NFT contract
|
|
15
|
+
*/
|
|
16
|
+
getNftInfo(contractAddress: `0x${string}`, tokenId: string): Promise<{
|
|
17
|
+
network: "mainnet";
|
|
18
|
+
contractAddress: `0x${string}`;
|
|
19
|
+
tokenId: string;
|
|
20
|
+
standard: NftStandard;
|
|
21
|
+
owner: `0x${string}` | null;
|
|
22
|
+
collection: {
|
|
23
|
+
name: string;
|
|
24
|
+
symbol: string;
|
|
25
|
+
totalSupply: string | undefined;
|
|
26
|
+
};
|
|
27
|
+
name: string;
|
|
28
|
+
description: string | undefined;
|
|
29
|
+
image: string | undefined;
|
|
30
|
+
metadataUri: string | null;
|
|
31
|
+
metadata: Record<string, unknown> | null;
|
|
32
|
+
attributes: {};
|
|
33
|
+
}>;
|
|
34
|
+
/**
|
|
35
|
+
* NFT balance for an owner (ERC-721 collection total or ERC-1155 id-specific balance).
|
|
36
|
+
* @param contractAddress - NFT collection contract
|
|
37
|
+
* @param ownerAddress - Holder wallet address
|
|
38
|
+
* @param tokenId - Required for ERC-1155; ignored for ERC-721 collection balance
|
|
39
|
+
* @returns Balance as decimal string and detected standard
|
|
40
|
+
* @throws When ERC-1155 is detected but `tokenId` is omitted
|
|
41
|
+
*/
|
|
42
|
+
getNftBalance(contractAddress: `0x${string}`, ownerAddress: `0x${string}`, tokenId?: string): Promise<{
|
|
43
|
+
network: "mainnet";
|
|
44
|
+
contractAddress: `0x${string}`;
|
|
45
|
+
ownerAddress: `0x${string}`;
|
|
46
|
+
tokenId: string | null;
|
|
47
|
+
balance: string;
|
|
48
|
+
standard: "ERC721";
|
|
49
|
+
} | {
|
|
50
|
+
network: "mainnet";
|
|
51
|
+
contractAddress: `0x${string}`;
|
|
52
|
+
ownerAddress: `0x${string}`;
|
|
53
|
+
tokenId: string;
|
|
54
|
+
balance: string;
|
|
55
|
+
standard: "ERC1155";
|
|
56
|
+
}>;
|
|
57
|
+
}
|
|
58
|
+
export {};
|
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ERC-721 and ERC-1155 NFT reads on Celo mainnet (metadata via token URI / IPFS).
|
|
3
|
+
*/
|
|
4
|
+
import { erc1155Abi, erc165Abi, erc721Abi, ERC1155_INTERFACE_ID, ERC721_INTERFACE_ID, } from "../abis/nft.js";
|
|
5
|
+
import { normalizeAddress } from "../utils/normalize-address.js";
|
|
6
|
+
function rewriteIpfsUri(uri) {
|
|
7
|
+
if (uri.startsWith("ipfs://")) {
|
|
8
|
+
return uri.replace("ipfs://", "https://ipfs.io/ipfs/");
|
|
9
|
+
}
|
|
10
|
+
return uri;
|
|
11
|
+
}
|
|
12
|
+
async function fetchMetadata(uri) {
|
|
13
|
+
if (!uri)
|
|
14
|
+
return null;
|
|
15
|
+
try {
|
|
16
|
+
const url = rewriteIpfsUri(uri);
|
|
17
|
+
const response = await fetch(url, { signal: AbortSignal.timeout(10_000) });
|
|
18
|
+
if (!response.ok)
|
|
19
|
+
return null;
|
|
20
|
+
return (await response.json());
|
|
21
|
+
}
|
|
22
|
+
catch {
|
|
23
|
+
return null;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
/** ERC-721 / ERC-1155 collection and balance reads with optional metadata fetch. */
|
|
27
|
+
export class NftService {
|
|
28
|
+
clientFactory;
|
|
29
|
+
constructor(clientFactory) {
|
|
30
|
+
this.clientFactory = clientFactory;
|
|
31
|
+
}
|
|
32
|
+
async assertIsContract(address) {
|
|
33
|
+
const { public: client } = this.clientFactory.getClients();
|
|
34
|
+
const bytecode = await client.getBytecode({ address });
|
|
35
|
+
if (!bytecode || bytecode === "0x") {
|
|
36
|
+
throw new Error(`${address} is not an NFT contract on Celo mainnet (no contract bytecode). ` +
|
|
37
|
+
"Verify the address is a deployed ERC-721 or ERC-1155 collection.");
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
async detectStandard(contractAddress) {
|
|
41
|
+
const { public: client } = this.clientFactory.getClients();
|
|
42
|
+
try {
|
|
43
|
+
const supports1155 = await client.readContract({
|
|
44
|
+
address: contractAddress,
|
|
45
|
+
abi: erc165Abi,
|
|
46
|
+
functionName: "supportsInterface",
|
|
47
|
+
args: [ERC1155_INTERFACE_ID],
|
|
48
|
+
});
|
|
49
|
+
if (supports1155)
|
|
50
|
+
return "ERC1155";
|
|
51
|
+
}
|
|
52
|
+
catch {
|
|
53
|
+
// fall through
|
|
54
|
+
}
|
|
55
|
+
try {
|
|
56
|
+
const supports721 = await client.readContract({
|
|
57
|
+
address: contractAddress,
|
|
58
|
+
abi: erc165Abi,
|
|
59
|
+
functionName: "supportsInterface",
|
|
60
|
+
args: [ERC721_INTERFACE_ID],
|
|
61
|
+
});
|
|
62
|
+
if (supports721)
|
|
63
|
+
return "ERC721";
|
|
64
|
+
}
|
|
65
|
+
catch {
|
|
66
|
+
// fall through
|
|
67
|
+
}
|
|
68
|
+
throw new Error(`${contractAddress} does not implement ERC-721 or ERC-1155 (ERC-165 check failed).`);
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Collection and token metadata for an ERC-721 or ERC-1155 contract.
|
|
72
|
+
* @param contractAddress - NFT collection contract
|
|
73
|
+
* @param tokenId - Token id as decimal string
|
|
74
|
+
* @returns Standard, owner, collection info, and fetched JSON metadata when available
|
|
75
|
+
* @throws When the address is not a deployed NFT contract
|
|
76
|
+
*/
|
|
77
|
+
async getNftInfo(contractAddress, tokenId) {
|
|
78
|
+
const contract = normalizeAddress(contractAddress, "contract address");
|
|
79
|
+
const { public: client } = this.clientFactory.getClients();
|
|
80
|
+
await this.assertIsContract(contract);
|
|
81
|
+
const standard = await this.detectStandard(contract);
|
|
82
|
+
const id = BigInt(tokenId);
|
|
83
|
+
let name;
|
|
84
|
+
let symbol;
|
|
85
|
+
let totalSupply;
|
|
86
|
+
let owner = null;
|
|
87
|
+
let metadataUri = null;
|
|
88
|
+
if (standard === "ERC721") {
|
|
89
|
+
const [collectionName, collectionSymbol, supply] = await Promise.all([
|
|
90
|
+
client
|
|
91
|
+
.readContract({
|
|
92
|
+
address: contract,
|
|
93
|
+
abi: erc721Abi,
|
|
94
|
+
functionName: "name",
|
|
95
|
+
})
|
|
96
|
+
.catch(() => undefined),
|
|
97
|
+
client
|
|
98
|
+
.readContract({
|
|
99
|
+
address: contract,
|
|
100
|
+
abi: erc721Abi,
|
|
101
|
+
functionName: "symbol",
|
|
102
|
+
})
|
|
103
|
+
.catch(() => undefined),
|
|
104
|
+
client
|
|
105
|
+
.readContract({
|
|
106
|
+
address: contract,
|
|
107
|
+
abi: erc721Abi,
|
|
108
|
+
functionName: "totalSupply",
|
|
109
|
+
})
|
|
110
|
+
.catch(() => undefined),
|
|
111
|
+
]);
|
|
112
|
+
name = collectionName;
|
|
113
|
+
symbol = collectionSymbol;
|
|
114
|
+
totalSupply = supply?.toString();
|
|
115
|
+
owner = await client
|
|
116
|
+
.readContract({
|
|
117
|
+
address: contract,
|
|
118
|
+
abi: erc721Abi,
|
|
119
|
+
functionName: "ownerOf",
|
|
120
|
+
args: [id],
|
|
121
|
+
})
|
|
122
|
+
.catch(() => null);
|
|
123
|
+
metadataUri = await client
|
|
124
|
+
.readContract({
|
|
125
|
+
address: contract,
|
|
126
|
+
abi: erc721Abi,
|
|
127
|
+
functionName: "tokenURI",
|
|
128
|
+
args: [id],
|
|
129
|
+
})
|
|
130
|
+
.catch(() => null);
|
|
131
|
+
}
|
|
132
|
+
else {
|
|
133
|
+
metadataUri = await client
|
|
134
|
+
.readContract({
|
|
135
|
+
address: contract,
|
|
136
|
+
abi: erc1155Abi,
|
|
137
|
+
functionName: "uri",
|
|
138
|
+
args: [id],
|
|
139
|
+
})
|
|
140
|
+
.catch(() => null);
|
|
141
|
+
}
|
|
142
|
+
const metadata = metadataUri ? await fetchMetadata(metadataUri) : null;
|
|
143
|
+
const image = typeof metadata?.image === "string"
|
|
144
|
+
? rewriteIpfsUri(metadata.image)
|
|
145
|
+
: undefined;
|
|
146
|
+
return {
|
|
147
|
+
network: "mainnet",
|
|
148
|
+
contractAddress: contract,
|
|
149
|
+
tokenId,
|
|
150
|
+
standard,
|
|
151
|
+
owner,
|
|
152
|
+
collection: {
|
|
153
|
+
name: name ?? `Unknown Collection (${contract.slice(0, 8)}...)`,
|
|
154
|
+
symbol: symbol ?? "UNKNOWN",
|
|
155
|
+
totalSupply,
|
|
156
|
+
},
|
|
157
|
+
name: (typeof metadata?.name === "string" ? metadata.name : undefined) ??
|
|
158
|
+
`Token #${tokenId}`,
|
|
159
|
+
description: typeof metadata?.description === "string"
|
|
160
|
+
? metadata.description
|
|
161
|
+
: undefined,
|
|
162
|
+
image,
|
|
163
|
+
metadataUri,
|
|
164
|
+
metadata,
|
|
165
|
+
attributes: metadata?.attributes ?? [],
|
|
166
|
+
};
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* NFT balance for an owner (ERC-721 collection total or ERC-1155 id-specific balance).
|
|
170
|
+
* @param contractAddress - NFT collection contract
|
|
171
|
+
* @param ownerAddress - Holder wallet address
|
|
172
|
+
* @param tokenId - Required for ERC-1155; ignored for ERC-721 collection balance
|
|
173
|
+
* @returns Balance as decimal string and detected standard
|
|
174
|
+
* @throws When ERC-1155 is detected but `tokenId` is omitted
|
|
175
|
+
*/
|
|
176
|
+
async getNftBalance(contractAddress, ownerAddress, tokenId) {
|
|
177
|
+
const contract = normalizeAddress(contractAddress, "contract address");
|
|
178
|
+
const owner = normalizeAddress(ownerAddress, "owner address");
|
|
179
|
+
const { public: client } = this.clientFactory.getClients();
|
|
180
|
+
await this.assertIsContract(contract);
|
|
181
|
+
const standard = await this.detectStandard(contract);
|
|
182
|
+
if (standard === "ERC721") {
|
|
183
|
+
try {
|
|
184
|
+
const balance = await client.readContract({
|
|
185
|
+
address: contract,
|
|
186
|
+
abi: erc721Abi,
|
|
187
|
+
functionName: "balanceOf",
|
|
188
|
+
args: [owner],
|
|
189
|
+
});
|
|
190
|
+
return {
|
|
191
|
+
network: "mainnet",
|
|
192
|
+
contractAddress: contract,
|
|
193
|
+
ownerAddress: owner,
|
|
194
|
+
tokenId: tokenId ?? null,
|
|
195
|
+
balance: balance.toString(),
|
|
196
|
+
standard,
|
|
197
|
+
};
|
|
198
|
+
}
|
|
199
|
+
catch (error) {
|
|
200
|
+
throw new Error(`Could not read ERC-721 balance for ${contract}: ${error instanceof Error ? error.message : String(error)}`);
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
if (!tokenId) {
|
|
204
|
+
throw new Error("Token ID is required for ERC1155 balance queries");
|
|
205
|
+
}
|
|
206
|
+
const balance = await client.readContract({
|
|
207
|
+
address: contract,
|
|
208
|
+
abi: erc1155Abi,
|
|
209
|
+
functionName: "balanceOf",
|
|
210
|
+
args: [owner, BigInt(tokenId)],
|
|
211
|
+
});
|
|
212
|
+
return {
|
|
213
|
+
network: "mainnet",
|
|
214
|
+
contractAddress: contract,
|
|
215
|
+
ownerAddress: owner,
|
|
216
|
+
tokenId,
|
|
217
|
+
balance: balance.toString(),
|
|
218
|
+
standard,
|
|
219
|
+
};
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
//# sourceMappingURL=nft.service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"nft.service.js","sourceRoot":"","sources":["../../../src/services/nft.service.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { SelfDeregistrationSession, SelfRefreshSession, SelfRegistrationSession } from "../clients/self-api.js";
|
|
2
|
+
export type SelfSessionKind = "registration" | "refresh" | "deregistration";
|
|
3
|
+
export type StoredSelfSession = {
|
|
4
|
+
kind: "registration";
|
|
5
|
+
session: SelfRegistrationSession;
|
|
6
|
+
createdAt: number;
|
|
7
|
+
} | {
|
|
8
|
+
kind: "refresh";
|
|
9
|
+
session: SelfRefreshSession;
|
|
10
|
+
createdAt: number;
|
|
11
|
+
} | {
|
|
12
|
+
kind: "deregistration";
|
|
13
|
+
session: SelfDeregistrationSession;
|
|
14
|
+
createdAt: number;
|
|
15
|
+
};
|
|
16
|
+
export declare function storeSelfSession(sessionToken: string, entry: StoredSelfSession): void;
|
|
17
|
+
export declare function getSelfSession(sessionToken: string): StoredSelfSession | undefined;
|
|
18
|
+
export declare function deleteSelfSession(sessionToken: string): void;
|
|
19
|
+
export declare function clearSelfSessionsForTests(): void;
|