@pushchain/core 6.0.20 → 6.0.21
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/CHANGELOG.md +48 -0
- package/package.json +1 -1
- package/src/lib/cache/cache.js +2 -0
- package/src/lib/constants/abi/index.d.ts +1 -0
- package/src/lib/constants/abi/index.js +8 -1
- package/src/lib/constants/abi/pc20.evm.d.ts +217 -0
- package/src/lib/constants/abi/pc20.evm.js +150 -0
- package/src/lib/constants/abi/prc20.evm.d.ts +172 -0
- package/src/lib/constants/abi/prc20.evm.js +97 -0
- package/src/lib/constants/abi/universalGatewayV0.json +1 -1
- package/src/lib/constants/chain.js +38 -8
- package/src/lib/constants/selectors.js +2 -2
- package/src/lib/constants/tokens.js +4 -3
- package/src/lib/formatters.js +16 -6
- package/src/lib/generated/uexecutor/v1/query.js +2 -4
- package/src/lib/generated/uexecutor/v1/types.d.ts +14 -0
- package/src/lib/generated/uexecutor/v1/types.js +90 -47
- package/src/lib/generated/uexecutor/v2/query.js +2 -4
- package/src/lib/generated/uexecutor/v2/types.d.ts +20 -0
- package/src/lib/generated/uexecutor/v2/types.js +49 -33
- package/src/lib/generated/v1/tx.js +30 -37
- package/src/lib/index.d.ts +3 -0
- package/src/lib/index.js +21 -3
- package/src/lib/internal/buffer.js +1 -2
- package/src/lib/orchestrator/cea-utils.js +73 -83
- package/src/lib/orchestrator/internals/account-manager.js +130 -139
- package/src/lib/orchestrator/internals/cascade.d.ts +0 -6
- package/src/lib/orchestrator/internals/cascade.js +1184 -1059
- package/src/lib/orchestrator/internals/confirmation.js +138 -148
- package/src/lib/orchestrator/internals/error-decoder.js +1 -1
- package/src/lib/orchestrator/internals/errors.js +12 -3
- package/src/lib/orchestrator/internals/execute-funds-only.d.ts +2 -2
- package/src/lib/orchestrator/internals/execute-funds-only.js +297 -259
- package/src/lib/orchestrator/internals/execute-funds-payload.d.ts +2 -2
- package/src/lib/orchestrator/internals/execute-funds-payload.js +220 -220
- package/src/lib/orchestrator/internals/execute-standard.d.ts +0 -8
- package/src/lib/orchestrator/internals/execute-standard.js +339 -342
- package/src/lib/orchestrator/internals/gas-calculator.js +497 -520
- package/src/lib/orchestrator/internals/gas-usd-sizer.js +101 -110
- package/src/lib/orchestrator/internals/gateway-client.js +102 -103
- package/src/lib/orchestrator/internals/helpers.js +30 -27
- package/src/lib/orchestrator/internals/inbound-tracker.js +234 -238
- package/src/lib/orchestrator/internals/outbound-sync.js +463 -452
- package/src/lib/orchestrator/internals/outbound-tracker.js +27 -34
- package/src/lib/orchestrator/internals/payload-builder.d.ts +2 -2
- package/src/lib/orchestrator/internals/payload-builder.js +119 -100
- package/src/lib/orchestrator/internals/pc-usd-oracle.js +121 -129
- package/src/lib/orchestrator/internals/pc20/address-codec.d.ts +31 -0
- package/src/lib/orchestrator/internals/pc20/address-codec.js +124 -0
- package/src/lib/orchestrator/internals/pc20/chain-namespace.d.ts +68 -0
- package/src/lib/orchestrator/internals/pc20/chain-namespace.js +136 -0
- package/src/lib/orchestrator/internals/pc20/errors.d.ts +160 -0
- package/src/lib/orchestrator/internals/pc20/errors.js +236 -0
- package/src/lib/orchestrator/internals/pc20/export.d.ts +172 -0
- package/src/lib/orchestrator/internals/pc20/export.js +412 -0
- package/src/lib/orchestrator/internals/pc20/gate.d.ts +67 -0
- package/src/lib/orchestrator/internals/pc20/gate.js +184 -0
- package/src/lib/orchestrator/internals/pc20/resolver.d.ts +187 -0
- package/src/lib/orchestrator/internals/pc20/resolver.js +658 -0
- package/src/lib/orchestrator/internals/pc20/svm.d.ts +189 -0
- package/src/lib/orchestrator/internals/pc20/svm.js +286 -0
- package/src/lib/orchestrator/internals/pc20/tracking.d.ts +46 -0
- package/src/lib/orchestrator/internals/pc20/tracking.js +109 -0
- package/src/lib/orchestrator/internals/preflight.js +1 -1
- package/src/lib/orchestrator/internals/progress-route-hooks.js +2 -2
- package/src/lib/orchestrator/internals/push-chain-tx.js +319 -329
- package/src/lib/orchestrator/internals/quote.js +90 -94
- package/src/lib/orchestrator/internals/rescue.js +76 -79
- package/src/lib/orchestrator/internals/response-builder.d.ts +28 -1
- package/src/lib/orchestrator/internals/response-builder.js +817 -701
- package/src/lib/orchestrator/internals/route-handlers.d.ts +7 -15
- package/src/lib/orchestrator/internals/route-handlers.js +1512 -1178
- package/src/lib/orchestrator/internals/signing.js +78 -83
- package/src/lib/orchestrator/internals/svm-bridge.d.ts +2 -2
- package/src/lib/orchestrator/internals/svm-bridge.js +161 -93
- package/src/lib/orchestrator/internals/svm-helpers.d.ts +15 -1
- package/src/lib/orchestrator/internals/svm-helpers.js +68 -24
- package/src/lib/orchestrator/internals/svm-rent.d.ts +19 -1
- package/src/lib/orchestrator/internals/svm-rent.js +163 -141
- package/src/lib/orchestrator/internals/tx-transformer.js +26 -23
- package/src/lib/orchestrator/internals/uea-manager.js +89 -86
- package/src/lib/orchestrator/max-pc-for-gas.js +5 -6
- package/src/lib/orchestrator/orchestrator.js +217 -200
- package/src/lib/orchestrator/orchestrator.types.d.ts +121 -1
- package/src/lib/orchestrator/orchestrator.types.js +19 -0
- package/src/lib/orchestrator/payload-builders.d.ts +2 -2
- package/src/lib/orchestrator/payload-builders.js +26 -24
- package/src/lib/orchestrator/route-detector.js +26 -9
- package/src/lib/orchestrator/svm-idl/ix-encoder.js +1 -2
- package/src/lib/orchestrator/svm-idl/normalize-address.js +2 -2
- package/src/lib/orchestrator/svm-idl/resolve.js +1 -2
- package/src/lib/price-fetch/price-fetch.js +67 -68
- package/src/lib/progress-hook/progress-hook.js +124 -72
- package/src/lib/push-chain/push-chain.js +171 -153
- package/src/lib/push-client/push-client.js +223 -237
- package/src/lib/universal/account/account.js +349 -365
- package/src/lib/universal/signer/signer.js +306 -294
- package/src/lib/universal-tx-detector/auto-detect.js +55 -60
- package/src/lib/universal-tx-detector/cascade.js +160 -172
- package/src/lib/universal-tx-detector/child-inbounds.js +67 -75
- package/src/lib/universal-tx-detector/classify.js +2 -3
- package/src/lib/universal-tx-detector/detector-svm.js +139 -147
- package/src/lib/universal-tx-detector/detector.js +145 -157
- package/src/lib/universal-tx-detector/normalize.js +7 -7
- package/src/lib/utils/external-tx-hash.js +1 -2
- package/src/lib/utils.d.ts +44 -0
- package/src/lib/utils.js +762 -683
- package/src/lib/vm-client/evm-client.js +186 -202
- package/src/lib/vm-client/svm-client.d.ts +1 -1
- package/src/lib/vm-client/svm-client.js +220 -224
- package/src/lib/vm-client/vm-client.types.d.ts +14 -2
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PC20 address codecs.
|
|
3
|
+
*
|
|
4
|
+
* UniversalCore stores every external identity as `bytes32`, with VM-specific
|
|
5
|
+
* encoding:
|
|
6
|
+
*
|
|
7
|
+
* EVM — the 20-byte address left-padded to 32 bytes.
|
|
8
|
+
* SVM — the raw 32-byte Solana public key, stored directly.
|
|
9
|
+
*
|
|
10
|
+
* The public API always speaks chain-native: checksummed hex for EVM, base58
|
|
11
|
+
* for Solana. These helpers are the only place the two representations meet.
|
|
12
|
+
*/
|
|
13
|
+
import { type Hex } from 'viem';
|
|
14
|
+
import { CHAIN } from '../../../constants/enums';
|
|
15
|
+
/** 32 zero bytes — the registry's "absent" value, and Solana's default pubkey. */
|
|
16
|
+
export declare const ZERO_BYTES32: "0x0000000000000000000000000000000000000000000000000000000000000000";
|
|
17
|
+
/** True when a `bytes32` registry read came back empty (unset mapping). */
|
|
18
|
+
export declare function isZeroBytes32(value: string): boolean;
|
|
19
|
+
/**
|
|
20
|
+
* Normalize a chain-native address to the registry's `bytes32` form.
|
|
21
|
+
*
|
|
22
|
+
* @throws {InvalidPC20AddressError} on a malformed or zero/default address.
|
|
23
|
+
*/
|
|
24
|
+
export declare function pc20AddressToBytes32(chain: CHAIN, address: string): Hex;
|
|
25
|
+
/**
|
|
26
|
+
* Convert a registry `bytes32` back to the chain-native representation:
|
|
27
|
+
* checksummed hex for EVM, base58 for Solana.
|
|
28
|
+
*
|
|
29
|
+
* @throws {InvalidPC20AddressError} on a malformed or zero value.
|
|
30
|
+
*/
|
|
31
|
+
export declare function pc20Bytes32ToAddress(chain: CHAIN, value: string): string;
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* PC20 address codecs.
|
|
4
|
+
*
|
|
5
|
+
* UniversalCore stores every external identity as `bytes32`, with VM-specific
|
|
6
|
+
* encoding:
|
|
7
|
+
*
|
|
8
|
+
* EVM — the 20-byte address left-padded to 32 bytes.
|
|
9
|
+
* SVM — the raw 32-byte Solana public key, stored directly.
|
|
10
|
+
*
|
|
11
|
+
* The public API always speaks chain-native: checksummed hex for EVM, base58
|
|
12
|
+
* for Solana. These helpers are the only place the two representations meet.
|
|
13
|
+
*/
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
exports.ZERO_BYTES32 = void 0;
|
|
16
|
+
exports.isZeroBytes32 = isZeroBytes32;
|
|
17
|
+
exports.pc20AddressToBytes32 = pc20AddressToBytes32;
|
|
18
|
+
exports.pc20Bytes32ToAddress = pc20Bytes32ToAddress;
|
|
19
|
+
const tslib_1 = require("tslib");
|
|
20
|
+
const viem_1 = require("viem");
|
|
21
|
+
const web3_js_1 = require("@solana/web3.js");
|
|
22
|
+
const bs58_1 = tslib_1.__importDefault(require("bs58"));
|
|
23
|
+
const enums_1 = require("../../../constants/enums");
|
|
24
|
+
const chain_namespace_1 = require("./chain-namespace");
|
|
25
|
+
const errors_1 = require("./errors");
|
|
26
|
+
/** 32 zero bytes — the registry's "absent" value, and Solana's default pubkey. */
|
|
27
|
+
exports.ZERO_BYTES32 = '0x0000000000000000000000000000000000000000000000000000000000000000';
|
|
28
|
+
const ZERO_EVM_ADDRESS = '0x0000000000000000000000000000000000000000';
|
|
29
|
+
/** True when a `bytes32` registry read came back empty (unset mapping). */
|
|
30
|
+
function isZeroBytes32(value) {
|
|
31
|
+
return /^0x0*$/i.test(value);
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Normalize a chain-native address to the registry's `bytes32` form.
|
|
35
|
+
*
|
|
36
|
+
* @throws {InvalidPC20AddressError} on a malformed or zero/default address.
|
|
37
|
+
*/
|
|
38
|
+
function pc20AddressToBytes32(chain, address) {
|
|
39
|
+
const vm = (0, chain_namespace_1.vmForChain)(chain);
|
|
40
|
+
return vm === enums_1.VM.SVM
|
|
41
|
+
? svmAddressToBytes32(chain, address)
|
|
42
|
+
: evmAddressToBytes32(chain, address);
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Convert a registry `bytes32` back to the chain-native representation:
|
|
46
|
+
* checksummed hex for EVM, base58 for Solana.
|
|
47
|
+
*
|
|
48
|
+
* @throws {InvalidPC20AddressError} on a malformed or zero value.
|
|
49
|
+
*/
|
|
50
|
+
function pc20Bytes32ToAddress(chain, value) {
|
|
51
|
+
const vm = (0, chain_namespace_1.vmForChain)(chain);
|
|
52
|
+
if (!(0, viem_1.isHex)(value) || value.length !== 66) {
|
|
53
|
+
throw new errors_1.InvalidPC20AddressError('Registry value is not a 32-byte hex string.', {
|
|
54
|
+
chain,
|
|
55
|
+
address: value,
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
if (isZeroBytes32(value)) {
|
|
59
|
+
throw new errors_1.InvalidPC20AddressError('Registry value is the zero identity.', {
|
|
60
|
+
chain,
|
|
61
|
+
address: value,
|
|
62
|
+
hint: 'The mapping is unset — check `deployed`/`known` before decoding.',
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
return vm === enums_1.VM.SVM ? svmBytes32ToAddress(value) : evmBytes32ToAddress(chain, value);
|
|
66
|
+
}
|
|
67
|
+
// ---------------------------------------------------------------------------
|
|
68
|
+
// EVM
|
|
69
|
+
// ---------------------------------------------------------------------------
|
|
70
|
+
function evmAddressToBytes32(chain, address) {
|
|
71
|
+
if (!(0, viem_1.isAddress)(address)) {
|
|
72
|
+
throw new errors_1.InvalidPC20AddressError('Not a valid 20-byte EVM address.', {
|
|
73
|
+
chain,
|
|
74
|
+
address,
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
if (address.toLowerCase() === ZERO_EVM_ADDRESS) {
|
|
78
|
+
throw new errors_1.InvalidPC20AddressError('Zero address is not a valid PC20 token.', {
|
|
79
|
+
chain,
|
|
80
|
+
address,
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
return (0, viem_1.padHex)((0, viem_1.getAddress)(address), { size: 32, dir: 'left' });
|
|
84
|
+
}
|
|
85
|
+
function evmBytes32ToAddress(chain, value) {
|
|
86
|
+
// An EVM identity occupies the low 20 bytes; anything in the high 12 bytes
|
|
87
|
+
// means this value was written for a different VM and must not be truncated
|
|
88
|
+
// into a plausible-looking address.
|
|
89
|
+
const highBytes = value.slice(2, 26);
|
|
90
|
+
if (!/^0*$/.test(highBytes)) {
|
|
91
|
+
throw new errors_1.InvalidPC20AddressError('Registry value has non-zero high bytes and is not a left-padded EVM address.', { chain, address: value, hint: 'This identity may belong to a non-EVM chain.' });
|
|
92
|
+
}
|
|
93
|
+
return (0, viem_1.getAddress)(`0x${value.slice(26)}`);
|
|
94
|
+
}
|
|
95
|
+
// ---------------------------------------------------------------------------
|
|
96
|
+
// SVM
|
|
97
|
+
// ---------------------------------------------------------------------------
|
|
98
|
+
function svmAddressToBytes32(chain, address) {
|
|
99
|
+
let key;
|
|
100
|
+
try {
|
|
101
|
+
// Accept both base58 (the normal form) and 32-byte hex, so a value read
|
|
102
|
+
// back off-chain can be round-tripped without the caller re-encoding it.
|
|
103
|
+
key = (0, viem_1.isHex)(address)
|
|
104
|
+
? new web3_js_1.PublicKey(Buffer.from(address.slice(2), 'hex'))
|
|
105
|
+
: new web3_js_1.PublicKey(address);
|
|
106
|
+
}
|
|
107
|
+
catch {
|
|
108
|
+
throw new errors_1.InvalidPC20AddressError('Not a valid Solana public key.', {
|
|
109
|
+
chain,
|
|
110
|
+
address,
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
if (key.equals(web3_js_1.PublicKey.default)) {
|
|
114
|
+
throw new errors_1.InvalidPC20AddressError('Default public key is not a valid PC20 mint.', {
|
|
115
|
+
chain,
|
|
116
|
+
address,
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
return `0x${Buffer.from(key.toBytes()).toString('hex')}`;
|
|
120
|
+
}
|
|
121
|
+
function svmBytes32ToAddress(value) {
|
|
122
|
+
return bs58_1.default.encode(Buffer.from(value.slice(2), 'hex'));
|
|
123
|
+
}
|
|
124
|
+
//# sourceMappingURL=address-codec.js.map
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Chain namespace mapping for PC20 — single source of truth.
|
|
3
|
+
*
|
|
4
|
+
* `chainNamespace` is the key for every PC20 registry read on UniversalCore
|
|
5
|
+
* (`getPC20Wrapper`, `getPC20Source`, `pc20FactoryByChain`,
|
|
6
|
+
* `getPC20ExportGasAndFees`, `pc20DeploymentGasOverhead`) and appears in the
|
|
7
|
+
* public PC20 result types.
|
|
8
|
+
*
|
|
9
|
+
* The contracts define it as the CAIP-2 chain identifier — see
|
|
10
|
+
* `push-chain-core-contracts/src/Interfaces/IUniversalCore.sol`:
|
|
11
|
+
*
|
|
12
|
+
* /// @param destChainNamespace Destination chain (CAIP-2, e.g., "eip155:1")
|
|
13
|
+
*
|
|
14
|
+
* ## Why this derives from CHAIN_INFO and not from the CHAIN enum value
|
|
15
|
+
*
|
|
16
|
+
* The `CHAIN` enum values look like CAIP-2 strings already, so identity is
|
|
17
|
+
* tempting. It is wrong. `CHAIN.PUSH_LOCALNET` is `'eip155:9001'` while its
|
|
18
|
+
* `CHAIN_INFO.chainId` is `'9000'`, and `CHAIN.PUSH_MAINNET`'s chainId is still
|
|
19
|
+
* the `'TBD'` placeholder. The rest of the SDK (`helpers.getChainNamespace`,
|
|
20
|
+
* `utils/external-tx-hash.chainFromNamespace`) already derives from
|
|
21
|
+
* `CHAIN_INFO`, so deriving here keeps one convention instead of introducing a
|
|
22
|
+
* second that silently disagrees on those two chains.
|
|
23
|
+
*
|
|
24
|
+
* The `'TBD'` placeholder is rejected outright. `'eip155:TBD'` is a
|
|
25
|
+
* syntactically fine string that matches nothing in the registry — exactly the
|
|
26
|
+
* kind of value that reads back as "not deployed".
|
|
27
|
+
*
|
|
28
|
+
* Do NOT confuse this with `VM_NAMESPACE` in `constants/chain.ts`, which is the
|
|
29
|
+
* CAIP-2 *prefix* only (`'eip155'` / `'solana'`). Passing a bare prefix to the
|
|
30
|
+
* registry silently misses.
|
|
31
|
+
*
|
|
32
|
+
* ## Why these throw
|
|
33
|
+
*
|
|
34
|
+
* An unmapped namespace returns `(0x0, known=false)` from the registry, which
|
|
35
|
+
* is indistinguishable from "this wrapper is not deployed yet". Returning a
|
|
36
|
+
* negative would surface a mapping bug as an empty receipt field or a spurious
|
|
37
|
+
* "not registered" error. Throwing keeps the failure legible.
|
|
38
|
+
*/
|
|
39
|
+
import { CHAIN, VM } from '../../../constants/enums';
|
|
40
|
+
/**
|
|
41
|
+
* Convert a supported `CHAIN` to the namespace string UniversalCore is keyed on.
|
|
42
|
+
*
|
|
43
|
+
* @throws {PC20UnknownChainNamespaceError} if the chain is unsupported or its
|
|
44
|
+
* chainId is still a placeholder.
|
|
45
|
+
*/
|
|
46
|
+
export declare function chainToNamespace(chain: CHAIN): string;
|
|
47
|
+
/**
|
|
48
|
+
* Convert a namespace string from chain or protobuf data back to a `CHAIN`.
|
|
49
|
+
*
|
|
50
|
+
* Used by the outbound tracking fallback, where `destinationChain` arrives as an
|
|
51
|
+
* untyped string from the node.
|
|
52
|
+
*
|
|
53
|
+
* @throws {PC20UnknownChainNamespaceError} if it maps to no supported chain.
|
|
54
|
+
*/
|
|
55
|
+
export declare function namespaceToChain(namespace: string): CHAIN;
|
|
56
|
+
/** Non-throwing variant for callers that legitimately probe an unknown value. */
|
|
57
|
+
export declare function tryNamespaceToChain(namespace: string): CHAIN | undefined;
|
|
58
|
+
/** Non-throwing variant, for building candidate chain lists. */
|
|
59
|
+
export declare function tryChainToNamespace(chain: CHAIN): string | undefined;
|
|
60
|
+
/** VM for a supported chain. Throws rather than defaulting to EVM. */
|
|
61
|
+
export declare function vmForChain(chain: CHAIN): VM;
|
|
62
|
+
/** True for any Push Chain network (never an external chain). */
|
|
63
|
+
export declare function isPushChain(chain: CHAIN): boolean;
|
|
64
|
+
/**
|
|
65
|
+
* Supported external chains that have a usable namespace — the default target
|
|
66
|
+
* set for deployment discovery when the caller passes no explicit `chains`.
|
|
67
|
+
*/
|
|
68
|
+
export declare function allExternalChains(): CHAIN[];
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Chain namespace mapping for PC20 — single source of truth.
|
|
4
|
+
*
|
|
5
|
+
* `chainNamespace` is the key for every PC20 registry read on UniversalCore
|
|
6
|
+
* (`getPC20Wrapper`, `getPC20Source`, `pc20FactoryByChain`,
|
|
7
|
+
* `getPC20ExportGasAndFees`, `pc20DeploymentGasOverhead`) and appears in the
|
|
8
|
+
* public PC20 result types.
|
|
9
|
+
*
|
|
10
|
+
* The contracts define it as the CAIP-2 chain identifier — see
|
|
11
|
+
* `push-chain-core-contracts/src/Interfaces/IUniversalCore.sol`:
|
|
12
|
+
*
|
|
13
|
+
* /// @param destChainNamespace Destination chain (CAIP-2, e.g., "eip155:1")
|
|
14
|
+
*
|
|
15
|
+
* ## Why this derives from CHAIN_INFO and not from the CHAIN enum value
|
|
16
|
+
*
|
|
17
|
+
* The `CHAIN` enum values look like CAIP-2 strings already, so identity is
|
|
18
|
+
* tempting. It is wrong. `CHAIN.PUSH_LOCALNET` is `'eip155:9001'` while its
|
|
19
|
+
* `CHAIN_INFO.chainId` is `'9000'`, and `CHAIN.PUSH_MAINNET`'s chainId is still
|
|
20
|
+
* the `'TBD'` placeholder. The rest of the SDK (`helpers.getChainNamespace`,
|
|
21
|
+
* `utils/external-tx-hash.chainFromNamespace`) already derives from
|
|
22
|
+
* `CHAIN_INFO`, so deriving here keeps one convention instead of introducing a
|
|
23
|
+
* second that silently disagrees on those two chains.
|
|
24
|
+
*
|
|
25
|
+
* The `'TBD'` placeholder is rejected outright. `'eip155:TBD'` is a
|
|
26
|
+
* syntactically fine string that matches nothing in the registry — exactly the
|
|
27
|
+
* kind of value that reads back as "not deployed".
|
|
28
|
+
*
|
|
29
|
+
* Do NOT confuse this with `VM_NAMESPACE` in `constants/chain.ts`, which is the
|
|
30
|
+
* CAIP-2 *prefix* only (`'eip155'` / `'solana'`). Passing a bare prefix to the
|
|
31
|
+
* registry silently misses.
|
|
32
|
+
*
|
|
33
|
+
* ## Why these throw
|
|
34
|
+
*
|
|
35
|
+
* An unmapped namespace returns `(0x0, known=false)` from the registry, which
|
|
36
|
+
* is indistinguishable from "this wrapper is not deployed yet". Returning a
|
|
37
|
+
* negative would surface a mapping bug as an empty receipt field or a spurious
|
|
38
|
+
* "not registered" error. Throwing keeps the failure legible.
|
|
39
|
+
*/
|
|
40
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
41
|
+
exports.chainToNamespace = chainToNamespace;
|
|
42
|
+
exports.namespaceToChain = namespaceToChain;
|
|
43
|
+
exports.tryNamespaceToChain = tryNamespaceToChain;
|
|
44
|
+
exports.tryChainToNamespace = tryChainToNamespace;
|
|
45
|
+
exports.vmForChain = vmForChain;
|
|
46
|
+
exports.isPushChain = isPushChain;
|
|
47
|
+
exports.allExternalChains = allExternalChains;
|
|
48
|
+
const enums_1 = require("../../../constants/enums");
|
|
49
|
+
const chain_1 = require("../../../constants/chain");
|
|
50
|
+
const errors_1 = require("./errors");
|
|
51
|
+
/** All `CHAIN` enum values (PUSH_TESTNET_DONUT aliases PUSH_TESTNET, so this de-dupes). */
|
|
52
|
+
const ALL_CHAINS = Array.from(new Set(Object.values(enums_1.CHAIN)));
|
|
53
|
+
/** chainId values that are placeholders rather than real identifiers. */
|
|
54
|
+
const PLACEHOLDER_CHAIN_IDS = new Set(['TBD', '', 'unknown']);
|
|
55
|
+
function deriveNamespace(chain) {
|
|
56
|
+
const info = chain_1.CHAIN_INFO[chain];
|
|
57
|
+
if (!info)
|
|
58
|
+
return undefined;
|
|
59
|
+
if (PLACEHOLDER_CHAIN_IDS.has(info.chainId))
|
|
60
|
+
return undefined;
|
|
61
|
+
return `${chain_1.VM_NAMESPACE[info.vm]}:${info.chainId}`;
|
|
62
|
+
}
|
|
63
|
+
const CHAIN_TO_NAMESPACE = new Map(ALL_CHAINS.flatMap((chain) => {
|
|
64
|
+
const ns = deriveNamespace(chain);
|
|
65
|
+
return ns ? [[chain, ns]] : [];
|
|
66
|
+
}));
|
|
67
|
+
const NAMESPACE_TO_CHAIN = new Map(Array.from(CHAIN_TO_NAMESPACE, ([chain, ns]) => [ns, chain]));
|
|
68
|
+
/**
|
|
69
|
+
* Convert a supported `CHAIN` to the namespace string UniversalCore is keyed on.
|
|
70
|
+
*
|
|
71
|
+
* @throws {PC20UnknownChainNamespaceError} if the chain is unsupported or its
|
|
72
|
+
* chainId is still a placeholder.
|
|
73
|
+
*/
|
|
74
|
+
function chainToNamespace(chain) {
|
|
75
|
+
const namespace = CHAIN_TO_NAMESPACE.get(chain);
|
|
76
|
+
if (!namespace) {
|
|
77
|
+
throw new errors_1.PC20UnknownChainNamespaceError(String(chain), {
|
|
78
|
+
chain: String(chain),
|
|
79
|
+
hint: 'This chain has no usable CAIP-2 chainId in CHAIN_INFO ' +
|
|
80
|
+
'(unsupported, or still a TBD placeholder).',
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
return namespace;
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Convert a namespace string from chain or protobuf data back to a `CHAIN`.
|
|
87
|
+
*
|
|
88
|
+
* Used by the outbound tracking fallback, where `destinationChain` arrives as an
|
|
89
|
+
* untyped string from the node.
|
|
90
|
+
*
|
|
91
|
+
* @throws {PC20UnknownChainNamespaceError} if it maps to no supported chain.
|
|
92
|
+
*/
|
|
93
|
+
function namespaceToChain(namespace) {
|
|
94
|
+
const chain = NAMESPACE_TO_CHAIN.get(namespace);
|
|
95
|
+
if (!chain) {
|
|
96
|
+
throw new errors_1.PC20UnknownChainNamespaceError(namespace, {
|
|
97
|
+
hint: 'Expected a CAIP-2 chain id (e.g. "eip155:11155111"), not a bare ' +
|
|
98
|
+
'namespace prefix such as "eip155".',
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
return chain;
|
|
102
|
+
}
|
|
103
|
+
/** Non-throwing variant for callers that legitimately probe an unknown value. */
|
|
104
|
+
function tryNamespaceToChain(namespace) {
|
|
105
|
+
return NAMESPACE_TO_CHAIN.get(namespace);
|
|
106
|
+
}
|
|
107
|
+
/** Non-throwing variant, for building candidate chain lists. */
|
|
108
|
+
function tryChainToNamespace(chain) {
|
|
109
|
+
return CHAIN_TO_NAMESPACE.get(chain);
|
|
110
|
+
}
|
|
111
|
+
/** VM for a supported chain. Throws rather than defaulting to EVM. */
|
|
112
|
+
function vmForChain(chain) {
|
|
113
|
+
const info = chain_1.CHAIN_INFO[chain];
|
|
114
|
+
if (!info) {
|
|
115
|
+
throw new errors_1.PC20UnknownChainNamespaceError(String(chain), {
|
|
116
|
+
chain: String(chain),
|
|
117
|
+
hint: 'Chain is not present in CHAIN_INFO.',
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
return info.vm;
|
|
121
|
+
}
|
|
122
|
+
/** True for any Push Chain network (never an external chain). */
|
|
123
|
+
function isPushChain(chain) {
|
|
124
|
+
// PUSH_TESTNET_DONUT is an alias of PUSH_TESTNET, so it is covered here.
|
|
125
|
+
return (chain === enums_1.CHAIN.PUSH_MAINNET ||
|
|
126
|
+
chain === enums_1.CHAIN.PUSH_TESTNET ||
|
|
127
|
+
chain === enums_1.CHAIN.PUSH_LOCALNET);
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Supported external chains that have a usable namespace — the default target
|
|
131
|
+
* set for deployment discovery when the caller passes no explicit `chains`.
|
|
132
|
+
*/
|
|
133
|
+
function allExternalChains() {
|
|
134
|
+
return ALL_CHAINS.filter((c) => !isPushChain(c) && CHAIN_TO_NAMESPACE.has(c));
|
|
135
|
+
}
|
|
136
|
+
//# sourceMappingURL=chain-namespace.js.map
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Typed PC20 errors.
|
|
3
|
+
*
|
|
4
|
+
* Every error carries a stable `code` discriminator so callers classify by
|
|
5
|
+
* `instanceof` or `err.code` rather than by parsing messages, and structured
|
|
6
|
+
* context fields (supplied chain, supplied address, expected chain, resolved
|
|
7
|
+
* namespace) plus a concise remediation hint.
|
|
8
|
+
*
|
|
9
|
+
* Two rules these must not break:
|
|
10
|
+
* - Never classify a token by symbol. PC20 identity is address-and-chain only.
|
|
11
|
+
* - Never embed raw RPC payloads in the message. Context fields are curated.
|
|
12
|
+
*/
|
|
13
|
+
export type PC20ErrorContext = {
|
|
14
|
+
/** Chain the caller supplied, when relevant. */
|
|
15
|
+
chain?: string;
|
|
16
|
+
/** Address the caller supplied, when relevant. */
|
|
17
|
+
address?: string;
|
|
18
|
+
/** Chain the SDK expected — signer chain, `from.chain`, or the Push chain. */
|
|
19
|
+
expectedChain?: string;
|
|
20
|
+
/** Resolved CAIP-2 namespace used for the registry read. */
|
|
21
|
+
chainNamespace?: string;
|
|
22
|
+
/** Short, actionable remediation. */
|
|
23
|
+
hint?: string;
|
|
24
|
+
};
|
|
25
|
+
/** Base class for all PC20 failures. `instanceof PC20Error` catches the family. */
|
|
26
|
+
export declare class PC20Error extends Error {
|
|
27
|
+
readonly code: string;
|
|
28
|
+
readonly chain?: string;
|
|
29
|
+
readonly address?: string;
|
|
30
|
+
readonly expectedChain?: string;
|
|
31
|
+
readonly chainNamespace?: string;
|
|
32
|
+
readonly hint?: string;
|
|
33
|
+
constructor(code: string, message: string, ctx?: PC20ErrorContext);
|
|
34
|
+
}
|
|
35
|
+
/** Address is malformed for the supplied chain's VM, or is the zero/default address. */
|
|
36
|
+
export declare class InvalidPC20AddressError extends PC20Error {
|
|
37
|
+
constructor(message: string, ctx?: PC20ErrorContext);
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* `funds.token.chain` does not match where the funds actually are — the signer's
|
|
41
|
+
* chain for a direct external route, `params.from.chain` for a CEA-origin route,
|
|
42
|
+
* or the Push chain for an export.
|
|
43
|
+
*
|
|
44
|
+
* This is the check that stops a wrapper address copied onto the wrong chain.
|
|
45
|
+
*/
|
|
46
|
+
export declare class PC20TokenChainMismatchError extends PC20Error {
|
|
47
|
+
constructor(ctx?: PC20ErrorContext);
|
|
48
|
+
}
|
|
49
|
+
/** UniversalCore has no source mapping for this wrapper on this chain. */
|
|
50
|
+
export declare class PC20WrapperNotRegisteredError extends PC20Error {
|
|
51
|
+
constructor(ctx?: PC20ErrorContext);
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Forward and reverse registry lookups disagree: `getPC20Source(wrapper)`
|
|
55
|
+
* resolved a source whose `getPC20Wrapper(source)` is a different address.
|
|
56
|
+
*
|
|
57
|
+
* A stale or partially-written registry entry. Never proceed — the burn would
|
|
58
|
+
* unlock the wrong Push token.
|
|
59
|
+
*/
|
|
60
|
+
export declare class PC20RegistryMismatchError extends PC20Error {
|
|
61
|
+
constructor(ctx?: PC20ErrorContext & {
|
|
62
|
+
resolvedWrapper?: string;
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* The live external gateway's configured `pc20Factory` differs from the
|
|
67
|
+
* reference factory (the destination Vault's, or UniversalCore's registry if
|
|
68
|
+
* exposed), or the factory does not recognize the wrapper.
|
|
69
|
+
*
|
|
70
|
+
* Proceeding risks the gateway taking the non-PC20 path for this token.
|
|
71
|
+
*/
|
|
72
|
+
export declare class PC20FactoryMismatchError extends PC20Error {
|
|
73
|
+
constructor(ctx?: PC20ErrorContext & {
|
|
74
|
+
gatewayFactory?: string;
|
|
75
|
+
registryFactory?: string;
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
/** Token does not implement `pc20Metadata()`, or the metadata fails validation. */
|
|
79
|
+
export declare class InvalidPC20MetadataError extends PC20Error {
|
|
80
|
+
constructor(message: string, ctx?: PC20ErrorContext);
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* A synthetic PRC20 address was supplied where a Push-native PC20 was expected.
|
|
84
|
+
*
|
|
85
|
+
* Distinct from {@link InvalidPC20MetadataError}: a PRC20 is a legitimate token
|
|
86
|
+
* on the wrong API, not a broken one. Kept separate so the message can point at
|
|
87
|
+
* the right call instead of reading as "your token is invalid".
|
|
88
|
+
*/
|
|
89
|
+
export declare class PC20ExpectedButPRC20Error extends PC20Error {
|
|
90
|
+
constructor(ctx?: PC20ErrorContext);
|
|
91
|
+
}
|
|
92
|
+
/** Destination chain has no configured PC20 factory, or is not supported for PC20. */
|
|
93
|
+
export declare class UnsupportedPC20DestinationError extends PC20Error {
|
|
94
|
+
constructor(ctx?: PC20ErrorContext);
|
|
95
|
+
}
|
|
96
|
+
/** Caller's balance of the wrapper (inbound) or Push source (export) is short. */
|
|
97
|
+
export declare class InsufficientPC20BalanceError extends PC20Error {
|
|
98
|
+
constructor(ctx?: PC20ErrorContext & {
|
|
99
|
+
required?: bigint;
|
|
100
|
+
available?: bigint;
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* The same address is registered on more than one chain, resolving to
|
|
105
|
+
* different Push sources, and no `chain` was supplied to disambiguate.
|
|
106
|
+
*
|
|
107
|
+
* Only reachable from the lookup utility's optional-chain path. Picking the
|
|
108
|
+
* first match would be the one way that convenience could actively mislead —
|
|
109
|
+
* the caller would get a confident answer about the wrong token.
|
|
110
|
+
*/
|
|
111
|
+
export declare class PC20AmbiguousAddressError extends PC20Error {
|
|
112
|
+
readonly candidates: Array<{
|
|
113
|
+
chain: string;
|
|
114
|
+
pushAddress: string;
|
|
115
|
+
}>;
|
|
116
|
+
constructor(address: string, candidates: Array<{
|
|
117
|
+
chain: string;
|
|
118
|
+
pushAddress: string;
|
|
119
|
+
}>);
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* A chain namespace could not be mapped in either direction.
|
|
123
|
+
*
|
|
124
|
+
* Thrown rather than returning a negative result: an unmapped namespace reads
|
|
125
|
+
* from the registry as "not deployed", hiding the actual bug.
|
|
126
|
+
*/
|
|
127
|
+
export declare class PC20UnknownChainNamespaceError extends PC20Error {
|
|
128
|
+
constructor(namespace: string, ctx?: PC20ErrorContext);
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* The destination wrapper address for a first export could not be predicted.
|
|
132
|
+
*
|
|
133
|
+
* Thrown strictly BEFORE approval. A first export commits the source token into
|
|
134
|
+
* VaultPC20 before the destination transfer is built, so an unverifiable
|
|
135
|
+
* prediction must abort rather than fall back to a guess.
|
|
136
|
+
*/
|
|
137
|
+
export declare class PC20WrapperPredictionUnavailableError extends PC20Error {
|
|
138
|
+
constructor(ctx?: PC20ErrorContext);
|
|
139
|
+
}
|
|
140
|
+
/** A PC20 export reverted after the source token was locked. Carries recovery context. */
|
|
141
|
+
export declare class PC20ExportRevertedError extends PC20Error {
|
|
142
|
+
readonly outboundTxId?: string;
|
|
143
|
+
readonly lockedAmount?: bigint;
|
|
144
|
+
readonly revertRecipient?: string;
|
|
145
|
+
constructor(ctx?: PC20ErrorContext & {
|
|
146
|
+
outboundTxId?: string;
|
|
147
|
+
lockedAmount?: bigint;
|
|
148
|
+
revertRecipient?: string;
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* A wrapper burn was about to be submitted without any Push-side payload.
|
|
153
|
+
*
|
|
154
|
+
* Until every supported Push Chain version treats selector-only PC20 payloads
|
|
155
|
+
* as an empty payload, broadcasting this shape can burn the wrapper and leave
|
|
156
|
+
* the canonical token permanently locked. The SDK therefore fails closed.
|
|
157
|
+
*/
|
|
158
|
+
export declare class PC20UnsafeEmptyPayloadError extends PC20Error {
|
|
159
|
+
constructor(ctx?: PC20ErrorContext);
|
|
160
|
+
}
|