@aifinpay/agent 1.8.4 → 2.0.0-rc.13
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/PAYMENT_RECEIPTS.md +110 -0
- package/README.md +93 -35
- package/dist/agent.d.ts +6 -1
- package/dist/agent.d.ts.map +1 -1
- package/dist/agent.js +50 -12
- package/dist/agent.js.map +1 -1
- package/dist/agentHistory.d.ts +15 -0
- package/dist/agentHistory.d.ts.map +1 -0
- package/dist/agentHistory.js +47 -0
- package/dist/agentHistory.js.map +1 -0
- package/dist/agentPassport.d.ts +95 -0
- package/dist/agentPassport.d.ts.map +1 -0
- package/dist/agentPassport.js +177 -0
- package/dist/agentPassport.js.map +1 -0
- package/dist/aifp1.d.ts +135 -8
- package/dist/aifp1.d.ts.map +1 -1
- package/dist/aifp1.js +317 -50
- package/dist/aifp1.js.map +1 -1
- package/dist/apiUrl.d.ts +3 -0
- package/dist/apiUrl.d.ts.map +1 -0
- package/dist/apiUrl.js +8 -0
- package/dist/apiUrl.js.map +1 -0
- package/dist/chains.d.ts +4 -0
- package/dist/chains.d.ts.map +1 -0
- package/dist/chains.js +24 -0
- package/dist/chains.js.map +1 -0
- package/dist/deploymentResolver.d.ts +87 -0
- package/dist/deploymentResolver.d.ts.map +1 -0
- package/dist/deploymentResolver.js +145 -0
- package/dist/deploymentResolver.js.map +1 -0
- package/dist/facilitators/aifinpay.d.ts +4 -5
- package/dist/facilitators/aifinpay.d.ts.map +1 -1
- package/dist/facilitators/aifinpay.js +49 -19
- package/dist/facilitators/aifinpay.js.map +1 -1
- package/dist/facilitators/base.d.ts +12 -1
- package/dist/facilitators/base.d.ts.map +1 -1
- package/dist/facilitators/detect.d.ts +3 -3
- package/dist/facilitators/detect.d.ts.map +1 -1
- package/dist/facilitators/detect.js +3 -22
- package/dist/facilitators/detect.js.map +1 -1
- package/dist/facilitators/standard-x402.d.ts +4 -8
- package/dist/facilitators/standard-x402.d.ts.map +1 -1
- package/dist/facilitators/standard-x402.js +218 -92
- package/dist/facilitators/standard-x402.js.map +1 -1
- package/dist/index.d.ts +24 -18
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +22 -34
- package/dist/index.js.map +1 -1
- package/dist/localIdentity.d.ts +17 -0
- package/dist/localIdentity.d.ts.map +1 -0
- package/dist/localIdentity.js +81 -0
- package/dist/localIdentity.js.map +1 -0
- package/dist/settlement.d.ts +198 -0
- package/dist/settlement.d.ts.map +1 -0
- package/dist/settlement.js +429 -0
- package/dist/settlement.js.map +1 -0
- package/dist/settlementHttp.d.ts +10 -0
- package/dist/settlementHttp.d.ts.map +1 -0
- package/dist/settlementHttp.js +70 -0
- package/dist/settlementHttp.js.map +1 -0
- package/dist/settlementV14.d.ts +136 -0
- package/dist/settlementV14.d.ts.map +1 -0
- package/dist/settlementV14.js +170 -0
- package/dist/settlementV14.js.map +1 -0
- package/dist/solanaDeploymentResolver.d.ts +90 -0
- package/dist/solanaDeploymentResolver.d.ts.map +1 -0
- package/dist/solanaDeploymentResolver.js +143 -0
- package/dist/solanaDeploymentResolver.js.map +1 -0
- package/dist/solanaV14Deployments.generated.d.ts +35 -0
- package/dist/solanaV14Deployments.generated.d.ts.map +1 -0
- package/dist/solanaV14Deployments.generated.js +61 -0
- package/dist/solanaV14Deployments.generated.js.map +1 -0
- package/dist/splitterRoutes.d.ts +120 -0
- package/dist/splitterRoutes.d.ts.map +1 -0
- package/dist/splitterRoutes.generated.d.ts +22 -0
- package/dist/splitterRoutes.generated.d.ts.map +1 -0
- package/dist/splitterRoutes.generated.js +459 -0
- package/dist/splitterRoutes.generated.js.map +1 -0
- package/dist/splitterRoutes.js +73 -0
- package/dist/splitterRoutes.js.map +1 -0
- package/dist/unifiedAgent.d.ts +28 -18
- package/dist/unifiedAgent.d.ts.map +1 -1
- package/dist/unifiedAgent.js +85 -325
- package/dist/unifiedAgent.js.map +1 -1
- package/dist/v14Deployments.generated.d.ts +53 -0
- package/dist/v14Deployments.generated.d.ts.map +1 -0
- package/dist/v14Deployments.generated.js +89 -0
- package/dist/v14Deployments.generated.js.map +1 -0
- package/dist/wallet.d.ts +11 -52
- package/dist/wallet.d.ts.map +1 -1
- package/dist/wallet.js +27 -51
- package/dist/wallet.js.map +1 -1
- package/package.json +7 -4
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* B2BSplitter v1.4 settlement — the client half.
|
|
3
|
+
*
|
|
4
|
+
* v1.4 inverts who authorises a payment. Through v1.3 the agent built its own
|
|
5
|
+
* calldata and settled unilaterally; the backend verified afterwards. In v1.4
|
|
6
|
+
* both entrypoints go through `_verifyQuote`, which requires a 65-byte ECDSA
|
|
7
|
+
* signature from a SIGN_OPERATOR_ROLE holder. The agent cannot produce one, so
|
|
8
|
+
* the quote arrives already signed and the agent's job is to CHECK it and
|
|
9
|
+
* submit it — never to construct it.
|
|
10
|
+
*
|
|
11
|
+
* That makes this module mostly refusals, and deliberately so. Spec:
|
|
12
|
+
* evm-contract@feat/v14_migration docs/V14_QUOTE_FORMAT.md §8, "SDK / Frontend
|
|
13
|
+
* Responsibilities". Each check below cites the clause it implements, because
|
|
14
|
+
* a check nobody can trace back to a requirement is a check somebody deletes.
|
|
15
|
+
*/
|
|
16
|
+
import { type PublicClient, type WalletClient, type Address, type Hex } from "viem";
|
|
17
|
+
/** The Quote struct, exactly as B2BSplitterV14 declares it. Field ORDER is part
|
|
18
|
+
* of the EIP-712 hash — this mirrors _QUOTE_TYPEHASH and must not be reordered. */
|
|
19
|
+
export interface V14Quote {
|
|
20
|
+
payer: Address;
|
|
21
|
+
merchant: Address;
|
|
22
|
+
token: Address;
|
|
23
|
+
grossAmount: string;
|
|
24
|
+
ipCreator: Address;
|
|
25
|
+
validUntil: string;
|
|
26
|
+
orderIdHash: Hex;
|
|
27
|
+
nonce: string;
|
|
28
|
+
routeId: Hex;
|
|
29
|
+
}
|
|
30
|
+
/** What `/v1/quote` returns under `settlement_call` when settlement_version is 1.4. */
|
|
31
|
+
export interface V14SettlementCall {
|
|
32
|
+
chain: string;
|
|
33
|
+
contract: Address;
|
|
34
|
+
splitter_version: "1.4";
|
|
35
|
+
route: string;
|
|
36
|
+
asset: string;
|
|
37
|
+
function: string;
|
|
38
|
+
arg_encoding: "struct+signature";
|
|
39
|
+
field_order: string[];
|
|
40
|
+
value_wei: string;
|
|
41
|
+
args: {
|
|
42
|
+
quote: V14Quote;
|
|
43
|
+
signature: Hex;
|
|
44
|
+
};
|
|
45
|
+
bound_to_payer?: Address;
|
|
46
|
+
nonce_at_signing?: string;
|
|
47
|
+
}
|
|
48
|
+
export declare class V14SettlementError extends Error {
|
|
49
|
+
readonly code: string;
|
|
50
|
+
constructor(code: string, message: string);
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Routes this SDK understands, by NAME.
|
|
54
|
+
*
|
|
55
|
+
* §8.7 requires an allow-list and says old SDKs must refuse routes added after
|
|
56
|
+
* they shipped rather than guess. Names rather than hashes because the contract
|
|
57
|
+
* derives one from the other — Profiles.routeId(name) == keccak256(bytes(name)),
|
|
58
|
+
* verified against the deployed Amoy Profiles on 2026-09-02 for both entries —
|
|
59
|
+
* so hardcoding the hashes would be storing a derived value and inviting the
|
|
60
|
+
* two to disagree.
|
|
61
|
+
*/
|
|
62
|
+
export declare const KNOWN_V14_ROUTES: readonly ["merchant-aifp1", "agent-x402"];
|
|
63
|
+
export type KnownV14Route = (typeof KNOWN_V14_ROUTES)[number];
|
|
64
|
+
export declare function routeIdOf(name: string): Hex;
|
|
65
|
+
/** name → routeId, for every route this SDK will submit. */
|
|
66
|
+
export declare function knownRouteIds(): Record<Hex, KnownV14Route>;
|
|
67
|
+
export interface V14ValidateOptions {
|
|
68
|
+
/** The off-chain order id, when the caller knows it (§8.3). Omitted means the
|
|
69
|
+
* orderIdHash cannot be checked, and this module says so rather than
|
|
70
|
+
* pretending it verified something. */
|
|
71
|
+
orderId?: string;
|
|
72
|
+
/** The wallet that will send the transaction. §8.2 and the contract's own
|
|
73
|
+
* `payer == msg.sender` make this the difference between a quote that
|
|
74
|
+
* settles and one that reverts after gas. */
|
|
75
|
+
payer?: Address;
|
|
76
|
+
/** Seconds of headroom required before validUntil. A quote that expires while
|
|
77
|
+
* the transaction is in the mempool reverts SignatureExpired and the agent
|
|
78
|
+
* pays for the attempt. */
|
|
79
|
+
minSecondsRemaining?: number;
|
|
80
|
+
nowMs?: number;
|
|
81
|
+
/** Extra route names this deployment understands. Additive only. */
|
|
82
|
+
allowRoutes?: readonly string[];
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Read-only structural checks. Success does not authenticate the signer,
|
|
86
|
+
* deployment, fees or treasury and does not authorize settlement.
|
|
87
|
+
*
|
|
88
|
+
* Throws on the first failure with a code, because these are not equivalent:
|
|
89
|
+
* an expired quote should be re-requested, a foreign payer is a caller bug, and
|
|
90
|
+
* an unknown route means this SDK is older than the deployment.
|
|
91
|
+
*/
|
|
92
|
+
export declare function validateV14SettlementCall(call: V14SettlementCall, opts?: V14ValidateOptions): {
|
|
93
|
+
route: string;
|
|
94
|
+
expiresInSeconds: number;
|
|
95
|
+
orderIdChecked: boolean;
|
|
96
|
+
};
|
|
97
|
+
/**
|
|
98
|
+
* §8.6 — never re-broadcast a settled quote.
|
|
99
|
+
*
|
|
100
|
+
* The contract keeps two things and they answer different questions:
|
|
101
|
+
* consumedNonce[payer][nonce] has THIS nonce already been spent
|
|
102
|
+
* payerNonce[payer] which nonce the contract will accept next
|
|
103
|
+
*
|
|
104
|
+
* A quote is submittable only if its nonce is unspent AND is the one the
|
|
105
|
+
* contract expects. Two outstanding quotes for one wallet cannot both settle:
|
|
106
|
+
* the second carries a stale nonce and reverts InvalidNonce. That is a property
|
|
107
|
+
* of the contract, so it is reported here rather than discovered on-chain.
|
|
108
|
+
*/
|
|
109
|
+
export declare function checkV14Submittable(publicClient: PublicClient, call: V14SettlementCall): Promise<{
|
|
110
|
+
submittable: true;
|
|
111
|
+
} | {
|
|
112
|
+
submittable: false;
|
|
113
|
+
reason: string;
|
|
114
|
+
code: string;
|
|
115
|
+
}>;
|
|
116
|
+
/**
|
|
117
|
+
* v1.4 signing is quarantined. Its current signed Quote omits mutable profile
|
|
118
|
+
* fees and treasury. RPC preflight cannot bind those values at execution time.
|
|
119
|
+
* Keep the exported API for callers to handle the refusal, but provide no
|
|
120
|
+
* bypass: re-enabling requires a contract-bound economics commitment, reviewed
|
|
121
|
+
* deployment/signer/token pins, approval handling and mined-success recovery.
|
|
122
|
+
* Validation and nonce inspection above remain read-only diagnostics.
|
|
123
|
+
*/
|
|
124
|
+
export declare function executeV14Settlement(_call: V14SettlementCall, _ctx: {
|
|
125
|
+
publicClient: PublicClient;
|
|
126
|
+
walletClient: WalletClient;
|
|
127
|
+
account: Address;
|
|
128
|
+
orderId?: string;
|
|
129
|
+
minSecondsRemaining?: number;
|
|
130
|
+
/** @deprecated Cannot bypass the v1.4 settlement quarantine. */
|
|
131
|
+
skipPreflight?: boolean;
|
|
132
|
+
}): Promise<{
|
|
133
|
+
hash: Hex;
|
|
134
|
+
route: string;
|
|
135
|
+
}>;
|
|
136
|
+
//# sourceMappingURL=settlementV14.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"settlementV14.d.ts","sourceRoot":"","sources":["../src/settlementV14.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* B2BSplitter v1.4 settlement — the client half.
|
|
3
|
+
*
|
|
4
|
+
* v1.4 inverts who authorises a payment. Through v1.3 the agent built its own
|
|
5
|
+
* calldata and settled unilaterally; the backend verified afterwards. In v1.4
|
|
6
|
+
* both entrypoints go through `_verifyQuote`, which requires a 65-byte ECDSA
|
|
7
|
+
* signature from a SIGN_OPERATOR_ROLE holder. The agent cannot produce one, so
|
|
8
|
+
* the quote arrives already signed and the agent's job is to CHECK it and
|
|
9
|
+
* submit it — never to construct it.
|
|
10
|
+
*
|
|
11
|
+
* That makes this module mostly refusals, and deliberately so. Spec:
|
|
12
|
+
* evm-contract@feat/v14_migration docs/V14_QUOTE_FORMAT.md §8, "SDK / Frontend
|
|
13
|
+
* Responsibilities". Each check below cites the clause it implements, because
|
|
14
|
+
* a check nobody can trace back to a requirement is a check somebody deletes.
|
|
15
|
+
*/
|
|
16
|
+
import { keccak256, stringToHex, parseAbi, } from "viem";
|
|
17
|
+
export class V14SettlementError extends Error {
|
|
18
|
+
code;
|
|
19
|
+
constructor(code, message) {
|
|
20
|
+
super(message);
|
|
21
|
+
this.name = "V14SettlementError";
|
|
22
|
+
this.code = code;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Routes this SDK understands, by NAME.
|
|
27
|
+
*
|
|
28
|
+
* §8.7 requires an allow-list and says old SDKs must refuse routes added after
|
|
29
|
+
* they shipped rather than guess. Names rather than hashes because the contract
|
|
30
|
+
* derives one from the other — Profiles.routeId(name) == keccak256(bytes(name)),
|
|
31
|
+
* verified against the deployed Amoy Profiles on 2026-09-02 for both entries —
|
|
32
|
+
* so hardcoding the hashes would be storing a derived value and inviting the
|
|
33
|
+
* two to disagree.
|
|
34
|
+
*/
|
|
35
|
+
export const KNOWN_V14_ROUTES = ["merchant-aifp1", "agent-x402"];
|
|
36
|
+
export function routeIdOf(name) {
|
|
37
|
+
return keccak256(stringToHex(name));
|
|
38
|
+
}
|
|
39
|
+
/** name → routeId, for every route this SDK will submit. */
|
|
40
|
+
export function knownRouteIds() {
|
|
41
|
+
const out = {};
|
|
42
|
+
for (const n of KNOWN_V14_ROUTES)
|
|
43
|
+
out[routeIdOf(n).toLowerCase()] = n;
|
|
44
|
+
return out;
|
|
45
|
+
}
|
|
46
|
+
const ZERO = "0x0000000000000000000000000000000000000000";
|
|
47
|
+
const lc = (s) => String(s || "").toLowerCase();
|
|
48
|
+
/**
|
|
49
|
+
* Read-only structural checks. Success does not authenticate the signer,
|
|
50
|
+
* deployment, fees or treasury and does not authorize settlement.
|
|
51
|
+
*
|
|
52
|
+
* Throws on the first failure with a code, because these are not equivalent:
|
|
53
|
+
* an expired quote should be re-requested, a foreign payer is a caller bug, and
|
|
54
|
+
* an unknown route means this SDK is older than the deployment.
|
|
55
|
+
*/
|
|
56
|
+
export function validateV14SettlementCall(call, opts = {}) {
|
|
57
|
+
const fail = (code, msg) => { throw new V14SettlementError(code, msg); };
|
|
58
|
+
if (!call || typeof call !== "object")
|
|
59
|
+
fail("V14_MALFORMED", "no settlement call");
|
|
60
|
+
if (call.splitter_version !== "1.4") {
|
|
61
|
+
fail("V14_WRONG_VERSION", `expected a v1.4 settlement call, got ${String(call.splitter_version)} — v1.2 and v1.3 settle through a different path`);
|
|
62
|
+
}
|
|
63
|
+
const q = call.args && call.args.quote;
|
|
64
|
+
const sig = call.args && call.args.signature;
|
|
65
|
+
if (!q || !sig)
|
|
66
|
+
fail("V14_MALFORMED", "settlement call carries no quote or no signature");
|
|
67
|
+
// §8.1 — the signature is the whole point. The contract requires exactly 65
|
|
68
|
+
// bytes and reverts InvalidSignatureLength on anything else, after gas.
|
|
69
|
+
if (!/^0x[0-9a-fA-F]{130}$/.test(sig)) {
|
|
70
|
+
fail("V14_BAD_SIGNATURE", `signature must be 65 bytes, got ${(String(sig).length - 2) / 2}`);
|
|
71
|
+
}
|
|
72
|
+
// §8.7 — refuse routes this SDK does not understand rather than submit blind.
|
|
73
|
+
const allowed = { ...knownRouteIds() };
|
|
74
|
+
for (const extra of opts.allowRoutes || [])
|
|
75
|
+
allowed[routeIdOf(extra).toLowerCase()] = extra;
|
|
76
|
+
const route = allowed[lc(q.routeId)];
|
|
77
|
+
if (!route) {
|
|
78
|
+
fail("V14_UNKNOWN_ROUTE", `routeId ${q.routeId} is not one this SDK understands (${Object.values(allowed).join(", ")}). ` +
|
|
79
|
+
`A route added after this SDK shipped is expected — upgrade rather than force it.`);
|
|
80
|
+
}
|
|
81
|
+
// §8.2 — the contract enforces payer == msg.sender. Catching it here costs
|
|
82
|
+
// nothing; catching it on-chain costs the gas of a reverted transaction.
|
|
83
|
+
if (opts.payer && lc(opts.payer) !== lc(q.payer)) {
|
|
84
|
+
fail("V14_WRONG_PAYER", `this quote is signed for ${q.payer} and cannot be settled by ${opts.payer} — request one for your own address`);
|
|
85
|
+
}
|
|
86
|
+
if (call.bound_to_payer && lc(call.bound_to_payer) !== lc(q.payer)) {
|
|
87
|
+
fail("V14_MALFORMED", "bound_to_payer disagrees with the signed quote — do not submit this");
|
|
88
|
+
}
|
|
89
|
+
// §8.3 — hash the order id locally and compare. This is what stops a backend
|
|
90
|
+
// (or anything between it and here) from binding your payment to a different
|
|
91
|
+
// order than the one you asked about.
|
|
92
|
+
let orderIdChecked = false;
|
|
93
|
+
if (opts.orderId !== undefined) {
|
|
94
|
+
if (lc(keccak256(stringToHex(opts.orderId))) !== lc(q.orderIdHash)) {
|
|
95
|
+
fail("V14_ORDER_MISMATCH", `this quote settles a different order: orderIdHash does not match keccak256("${opts.orderId}")`);
|
|
96
|
+
}
|
|
97
|
+
orderIdChecked = true;
|
|
98
|
+
}
|
|
99
|
+
// §8.4 — expiry. Checked with headroom, because the relevant moment is when
|
|
100
|
+
// the transaction is MINED, not when it is signed.
|
|
101
|
+
const now = Math.floor((opts.nowMs ?? Date.now()) / 1000);
|
|
102
|
+
const expiresIn = Number(BigInt(q.validUntil) - BigInt(now));
|
|
103
|
+
const need = opts.minSecondsRemaining ?? 30;
|
|
104
|
+
if (expiresIn <= 0) {
|
|
105
|
+
fail("V14_EXPIRED", `quote expired ${-expiresIn}s ago — request a fresh one, do not submit this`);
|
|
106
|
+
}
|
|
107
|
+
if (expiresIn < need) {
|
|
108
|
+
fail("V14_EXPIRING", `quote expires in ${expiresIn}s, less than the ${need}s of headroom required — ` +
|
|
109
|
+
`it would likely revert SignatureExpired after you have paid gas`);
|
|
110
|
+
}
|
|
111
|
+
// §8.5 — msg.value must equal grossAmount exactly for native. The contract
|
|
112
|
+
// reverts IncorrectNativeValue on any difference, in either direction.
|
|
113
|
+
if (lc(q.token) === ZERO && String(call.value_wei) !== String(q.grossAmount)) {
|
|
114
|
+
fail("V14_VALUE_MISMATCH", `value_wei (${call.value_wei}) must equal the signed grossAmount (${q.grossAmount})`);
|
|
115
|
+
}
|
|
116
|
+
return { route: route, expiresInSeconds: expiresIn, orderIdChecked };
|
|
117
|
+
}
|
|
118
|
+
const NONCE_ABI = parseAbi([
|
|
119
|
+
"function consumedNonce(address,uint256) view returns (bool)",
|
|
120
|
+
"function payerNonce(address) view returns (uint256)",
|
|
121
|
+
"function paused() view returns (bool)",
|
|
122
|
+
]);
|
|
123
|
+
/**
|
|
124
|
+
* §8.6 — never re-broadcast a settled quote.
|
|
125
|
+
*
|
|
126
|
+
* The contract keeps two things and they answer different questions:
|
|
127
|
+
* consumedNonce[payer][nonce] has THIS nonce already been spent
|
|
128
|
+
* payerNonce[payer] which nonce the contract will accept next
|
|
129
|
+
*
|
|
130
|
+
* A quote is submittable only if its nonce is unspent AND is the one the
|
|
131
|
+
* contract expects. Two outstanding quotes for one wallet cannot both settle:
|
|
132
|
+
* the second carries a stale nonce and reverts InvalidNonce. That is a property
|
|
133
|
+
* of the contract, so it is reported here rather than discovered on-chain.
|
|
134
|
+
*/
|
|
135
|
+
export async function checkV14Submittable(publicClient, call) {
|
|
136
|
+
const q = call.args.quote;
|
|
137
|
+
const [spent, expected, paused] = await Promise.all([
|
|
138
|
+
publicClient.readContract({ address: call.contract, abi: NONCE_ABI, functionName: "consumedNonce", args: [q.payer, BigInt(q.nonce)] }),
|
|
139
|
+
publicClient.readContract({ address: call.contract, abi: NONCE_ABI, functionName: "payerNonce", args: [q.payer] }),
|
|
140
|
+
publicClient.readContract({ address: call.contract, abi: NONCE_ABI, functionName: "paused" }),
|
|
141
|
+
]);
|
|
142
|
+
if (paused) {
|
|
143
|
+
return { submittable: false, code: "V14_PAUSED",
|
|
144
|
+
reason: "the splitter is paused — every settlement reverts until it is unpaused" };
|
|
145
|
+
}
|
|
146
|
+
if (spent) {
|
|
147
|
+
return { submittable: false, code: "V14_ALREADY_SETTLED",
|
|
148
|
+
reason: `nonce ${q.nonce} has already been spent by ${q.payer} — this quote is settled, do not pay twice` };
|
|
149
|
+
}
|
|
150
|
+
if (BigInt(expected) !== BigInt(q.nonce)) {
|
|
151
|
+
return { submittable: false, code: "V14_STALE_NONCE",
|
|
152
|
+
reason: `this quote was signed at nonce ${q.nonce} but the contract now expects ${expected} — ` +
|
|
153
|
+
`another payment from this wallet settled first; request a fresh quote` };
|
|
154
|
+
}
|
|
155
|
+
return { submittable: true };
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* v1.4 signing is quarantined. Its current signed Quote omits mutable profile
|
|
159
|
+
* fees and treasury. RPC preflight cannot bind those values at execution time.
|
|
160
|
+
* Keep the exported API for callers to handle the refusal, but provide no
|
|
161
|
+
* bypass: re-enabling requires a contract-bound economics commitment, reviewed
|
|
162
|
+
* deployment/signer/token pins, approval handling and mined-success recovery.
|
|
163
|
+
* Validation and nonce inspection above remain read-only diagnostics.
|
|
164
|
+
*/
|
|
165
|
+
export async function executeV14Settlement(_call, _ctx) {
|
|
166
|
+
throw new V14SettlementError("V14_SETTLEMENT_DISABLED", "v1.4 settlement is disabled: signed quotes do not bind mutable fees and treasury. " +
|
|
167
|
+
"Use a separately reviewed v1.3 route or wait for the contract and SDK upgrade; " +
|
|
168
|
+
"do not manually submit this quote or automatically fall back to another contract.");
|
|
169
|
+
}
|
|
170
|
+
//# sourceMappingURL=settlementV14.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"settlementV14.js","sourceRoot":"","sources":["../src/settlementV14.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AIFINP-224 — SDK Environment & Protocol Version resolver (Solana).
|
|
3
|
+
*
|
|
4
|
+
* The Solana sibling of deploymentResolver.ts (AIFINP-223). Same idea — one
|
|
5
|
+
* place that answers "which deployment does the SDK use?" given an environment,
|
|
6
|
+
* a network and a requested version — shaped for Solana, where a deployment is
|
|
7
|
+
* a base58 program id + IDL rather than an EVM address record.
|
|
8
|
+
*
|
|
9
|
+
* Two axes, mirroring the EVM resolver:
|
|
10
|
+
* environment — "dev" | "prod". Development supports devnet only; production
|
|
11
|
+
* uses mainnet-beta. Both read their v1.4 artifacts from solana-contract's
|
|
12
|
+
* dev branch (bundled in solanaV14Deployments.generated.ts).
|
|
13
|
+
* version — "v1.4" | "auto" (and "v1.2" is accepted at the type level for
|
|
14
|
+
* parity with EVM). An explicit "v1.4" never silently downgrades.
|
|
15
|
+
*
|
|
16
|
+
* FALLBACK DIFFERS FROM EVM — READ THIS. The EVM resolver falls back v1.4 -> v1.2.
|
|
17
|
+
* Solana has NO v1.2-equivalent splitter: the old program was closed and removed
|
|
18
|
+
* from mainnet, and the SDK never bundled it (it reads the Solana program id at
|
|
19
|
+
* runtime from the bridge's pay_solana challenge). So there is nothing to fall
|
|
20
|
+
* back to. Therefore:
|
|
21
|
+
* - "auto" resolves v1.4 where deployed, and otherwise throws
|
|
22
|
+
* NoSolanaDeploymentError (no invented downgrade).
|
|
23
|
+
* - an explicit "v1.2" always throws SolanaV12UnavailableError, because no
|
|
24
|
+
* Solana v1.2 deployment exists.
|
|
25
|
+
* This is an open product question for Paul: whether the EVM v1.2/v1.4 fallback
|
|
26
|
+
* model should map onto Solana at all. Until a real Solana fallback exists, this
|
|
27
|
+
* resolver refuses to pretend one does.
|
|
28
|
+
*
|
|
29
|
+
* Program ids live in solanaV14Deployments.generated.ts, never inline here —
|
|
30
|
+
* this module is selection logic only.
|
|
31
|
+
*/
|
|
32
|
+
import { DeploymentResolverError, type SdkEnvironment } from "./deploymentResolver.js";
|
|
33
|
+
import { type SolanaV14Deployment } from "./solanaV14Deployments.generated.js";
|
|
34
|
+
/** Selectable protocol versions on the request side. "v1.2" exists for parity
|
|
35
|
+
* with the EVM selector but has no Solana deployment behind it. */
|
|
36
|
+
export type SolanaProtocolVersion = "v1.2" | "v1.4";
|
|
37
|
+
/** What a caller may ask for. "auto" (the default) resolves v1.4, or throws if
|
|
38
|
+
* it is not deployed for the environment+network — Solana has no fallback. */
|
|
39
|
+
export type SolanaRequestedVersion = SolanaProtocolVersion | "auto";
|
|
40
|
+
export interface ResolveSolanaDeploymentOptions {
|
|
41
|
+
environment: SdkEnvironment;
|
|
42
|
+
/** Cluster name: "devnet", or "mainnet"/"mainnet-beta". Case-insensitive. */
|
|
43
|
+
network: string;
|
|
44
|
+
/** Defaults to "auto". */
|
|
45
|
+
version?: SolanaRequestedVersion;
|
|
46
|
+
}
|
|
47
|
+
/** The resolved Solana deployment. Only v1.4 is ever returned; the field is
|
|
48
|
+
* kept for symmetry with the EVM resolver's discriminated union. */
|
|
49
|
+
export interface ResolvedSolanaDeployment {
|
|
50
|
+
version: "v1.4";
|
|
51
|
+
environment: SdkEnvironment;
|
|
52
|
+
network: "devnet" | "mainnet";
|
|
53
|
+
programId: string;
|
|
54
|
+
deployment: SolanaV14Deployment;
|
|
55
|
+
}
|
|
56
|
+
/** The development environment was asked for a cluster other than devnet. */
|
|
57
|
+
export declare class UnsupportedSolanaDevNetworkError extends DeploymentResolverError {
|
|
58
|
+
readonly network: string;
|
|
59
|
+
constructor(network: string);
|
|
60
|
+
}
|
|
61
|
+
/** Explicit "v1.4" requested but not deployed for this environment+network.
|
|
62
|
+
* Thrown rather than downgrading. */
|
|
63
|
+
export declare class SolanaVersionUnavailableError extends DeploymentResolverError {
|
|
64
|
+
readonly requested: SolanaProtocolVersion;
|
|
65
|
+
constructor(requested: SolanaProtocolVersion, environment: SdkEnvironment, network: string);
|
|
66
|
+
}
|
|
67
|
+
/** Explicit "v1.2" requested — no Solana v1.2 splitter exists at all. Distinct
|
|
68
|
+
* from SolanaVersionUnavailableError so callers can tell "not on this network"
|
|
69
|
+
* from "does not exist on Solana". */
|
|
70
|
+
export declare class SolanaV12UnavailableError extends DeploymentResolverError {
|
|
71
|
+
constructor();
|
|
72
|
+
}
|
|
73
|
+
/** No Solana v1.4 deployment exists for this environment+network, and Solana
|
|
74
|
+
* has no fallback version. */
|
|
75
|
+
export declare class NoSolanaDeploymentError extends DeploymentResolverError {
|
|
76
|
+
constructor(environment: SdkEnvironment, network: string);
|
|
77
|
+
}
|
|
78
|
+
/** Is a Solana v1.4 deployment available for this environment+network? */
|
|
79
|
+
export declare function isSolanaV14Available(environment: SdkEnvironment, network: string): boolean;
|
|
80
|
+
/**
|
|
81
|
+
* Resolve the Solana deployment the SDK should use. The single source of truth
|
|
82
|
+
* for Solana environment + protocol-version selection.
|
|
83
|
+
*
|
|
84
|
+
* @throws UnsupportedSolanaDevNetworkError dev asked for a non-devnet cluster
|
|
85
|
+
* @throws SolanaV12UnavailableError explicit v1.2 (none exists on Solana)
|
|
86
|
+
* @throws SolanaVersionUnavailableError explicit v1.4 not deployed here
|
|
87
|
+
* @throws NoSolanaDeploymentError auto, but no v1.4 for this env+network
|
|
88
|
+
*/
|
|
89
|
+
export declare function resolveSolanaDeployment(options: ResolveSolanaDeploymentOptions): ResolvedSolanaDeployment;
|
|
90
|
+
//# sourceMappingURL=solanaDeploymentResolver.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"solanaDeploymentResolver.d.ts","sourceRoot":"","sources":["../src/solanaDeploymentResolver.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,OAAO,EAAE,uBAAuB,EAAE,KAAK,cAAc,EAAE,MAAM,yBAAyB,CAAC;AACvF,OAAO,EAGL,KAAK,mBAAmB,EACzB,MAAM,qCAAqC,CAAC;AAE7C;oEACoE;AACpE,MAAM,MAAM,qBAAqB,GAAG,MAAM,GAAG,MAAM,CAAC;AAEpD;+EAC+E;AAC/E,MAAM,MAAM,sBAAsB,GAAG,qBAAqB,GAAG,MAAM,CAAC;AAEpE,MAAM,WAAW,8BAA8B;IAC7C,WAAW,EAAE,cAAc,CAAC;IAC5B,6EAA6E;IAC7E,OAAO,EAAE,MAAM,CAAC;IAChB,0BAA0B;IAC1B,OAAO,CAAC,EAAE,sBAAsB,CAAC;CAClC;AAED;qEACqE;AACrE,MAAM,WAAW,wBAAwB;IACvC,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,cAAc,CAAC;IAC5B,OAAO,EAAE,QAAQ,GAAG,SAAS,CAAC;IAC9B,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,mBAAmB,CAAC;CACjC;AAID,6EAA6E;AAC7E,qBAAa,gCAAiC,SAAQ,uBAAuB;IAC3E,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;gBACb,OAAO,EAAE,MAAM;CAS5B;AAED;sCACsC;AACtC,qBAAa,6BAA8B,SAAQ,uBAAuB;IACxE,QAAQ,CAAC,SAAS,EAAE,qBAAqB,CAAC;gBAExC,SAAS,EAAE,qBAAqB,EAChC,WAAW,EAAE,cAAc,EAC3B,OAAO,EAAE,MAAM;CAUlB;AAED;;uCAEuC;AACvC,qBAAa,yBAA0B,SAAQ,uBAAuB;;CASrE;AAED;+BAC+B;AAC/B,qBAAa,uBAAwB,SAAQ,uBAAuB;gBACtD,WAAW,EAAE,cAAc,EAAE,OAAO,EAAE,MAAM;CAOzD;AAsBD,0EAA0E;AAC1E,wBAAgB,oBAAoB,CAClC,WAAW,EAAE,cAAc,EAC3B,OAAO,EAAE,MAAM,GACd,OAAO,CAET;AAID;;;;;;;;GAQG;AACH,wBAAgB,uBAAuB,CACrC,OAAO,EAAE,8BAA8B,GACtC,wBAAwB,CAyC1B"}
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AIFINP-224 — SDK Environment & Protocol Version resolver (Solana).
|
|
3
|
+
*
|
|
4
|
+
* The Solana sibling of deploymentResolver.ts (AIFINP-223). Same idea — one
|
|
5
|
+
* place that answers "which deployment does the SDK use?" given an environment,
|
|
6
|
+
* a network and a requested version — shaped for Solana, where a deployment is
|
|
7
|
+
* a base58 program id + IDL rather than an EVM address record.
|
|
8
|
+
*
|
|
9
|
+
* Two axes, mirroring the EVM resolver:
|
|
10
|
+
* environment — "dev" | "prod". Development supports devnet only; production
|
|
11
|
+
* uses mainnet-beta. Both read their v1.4 artifacts from solana-contract's
|
|
12
|
+
* dev branch (bundled in solanaV14Deployments.generated.ts).
|
|
13
|
+
* version — "v1.4" | "auto" (and "v1.2" is accepted at the type level for
|
|
14
|
+
* parity with EVM). An explicit "v1.4" never silently downgrades.
|
|
15
|
+
*
|
|
16
|
+
* FALLBACK DIFFERS FROM EVM — READ THIS. The EVM resolver falls back v1.4 -> v1.2.
|
|
17
|
+
* Solana has NO v1.2-equivalent splitter: the old program was closed and removed
|
|
18
|
+
* from mainnet, and the SDK never bundled it (it reads the Solana program id at
|
|
19
|
+
* runtime from the bridge's pay_solana challenge). So there is nothing to fall
|
|
20
|
+
* back to. Therefore:
|
|
21
|
+
* - "auto" resolves v1.4 where deployed, and otherwise throws
|
|
22
|
+
* NoSolanaDeploymentError (no invented downgrade).
|
|
23
|
+
* - an explicit "v1.2" always throws SolanaV12UnavailableError, because no
|
|
24
|
+
* Solana v1.2 deployment exists.
|
|
25
|
+
* This is an open product question for Paul: whether the EVM v1.2/v1.4 fallback
|
|
26
|
+
* model should map onto Solana at all. Until a real Solana fallback exists, this
|
|
27
|
+
* resolver refuses to pretend one does.
|
|
28
|
+
*
|
|
29
|
+
* Program ids live in solanaV14Deployments.generated.ts, never inline here —
|
|
30
|
+
* this module is selection logic only.
|
|
31
|
+
*/
|
|
32
|
+
import { DeploymentResolverError } from "./deploymentResolver.js";
|
|
33
|
+
import { SOLANA_DEV_NETWORKS, SOLANA_V14_DEPLOYMENTS, } from "./solanaV14Deployments.generated.js";
|
|
34
|
+
// ── Errors (parallel to the EVM resolver, Solana-worded) ─────────────────────
|
|
35
|
+
/** The development environment was asked for a cluster other than devnet. */
|
|
36
|
+
export class UnsupportedSolanaDevNetworkError extends DeploymentResolverError {
|
|
37
|
+
network;
|
|
38
|
+
constructor(network) {
|
|
39
|
+
super(`Development environment supports ${SOLANA_DEV_NETWORKS.join(", ")} only; ` +
|
|
40
|
+
`"${network}" is not a supported Solana development cluster. Use ` +
|
|
41
|
+
`environment "prod" for mainnet.`);
|
|
42
|
+
this.name = "UnsupportedSolanaDevNetworkError";
|
|
43
|
+
this.network = network;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
/** Explicit "v1.4" requested but not deployed for this environment+network.
|
|
47
|
+
* Thrown rather than downgrading. */
|
|
48
|
+
export class SolanaVersionUnavailableError extends DeploymentResolverError {
|
|
49
|
+
requested;
|
|
50
|
+
constructor(requested, environment, network) {
|
|
51
|
+
super(`Solana ${requested} is not deployed for ${environment}/${network}. It ` +
|
|
52
|
+
`was requested explicitly, so the SDK will not substitute another ` +
|
|
53
|
+
`version.`);
|
|
54
|
+
this.name = "SolanaVersionUnavailableError";
|
|
55
|
+
this.requested = requested;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
/** Explicit "v1.2" requested — no Solana v1.2 splitter exists at all. Distinct
|
|
59
|
+
* from SolanaVersionUnavailableError so callers can tell "not on this network"
|
|
60
|
+
* from "does not exist on Solana". */
|
|
61
|
+
export class SolanaV12UnavailableError extends DeploymentResolverError {
|
|
62
|
+
constructor() {
|
|
63
|
+
super(`Solana has no v1.2 deployment. The previous Solana program was closed ` +
|
|
64
|
+
`and there is no v1.2-equivalent to fall back to; only v1.4 is available. ` +
|
|
65
|
+
`Use version "v1.4" or "auto".`);
|
|
66
|
+
this.name = "SolanaV12UnavailableError";
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
/** No Solana v1.4 deployment exists for this environment+network, and Solana
|
|
70
|
+
* has no fallback version. */
|
|
71
|
+
export class NoSolanaDeploymentError extends DeploymentResolverError {
|
|
72
|
+
constructor(environment, network) {
|
|
73
|
+
super(`No Solana v1.4 deployment is known for ${environment}/${network}, and ` +
|
|
74
|
+
`Solana has no fallback version.`);
|
|
75
|
+
this.name = "NoSolanaDeploymentError";
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
// ── Lookups ──────────────────────────────────────────────────────────────────
|
|
79
|
+
/** Normalise a cluster name: lower-cased, and "mainnet-beta" -> "mainnet". */
|
|
80
|
+
function normalizeNetwork(network) {
|
|
81
|
+
const n = network.trim().toLowerCase();
|
|
82
|
+
return n === "mainnet-beta" ? "mainnet" : n;
|
|
83
|
+
}
|
|
84
|
+
/** The v1.4 deployment for this environment+network, or undefined. A record is
|
|
85
|
+
* only valid for the environment it was deployed under: devnet is dev-only and
|
|
86
|
+
* must never resolve under "prod", and vice versa. */
|
|
87
|
+
function findSolanaV14(environment, network) {
|
|
88
|
+
const entry = SOLANA_V14_DEPLOYMENTS[network];
|
|
89
|
+
if (!entry)
|
|
90
|
+
return undefined;
|
|
91
|
+
return entry.environment === environment ? entry : undefined;
|
|
92
|
+
}
|
|
93
|
+
/** Is a Solana v1.4 deployment available for this environment+network? */
|
|
94
|
+
export function isSolanaV14Available(environment, network) {
|
|
95
|
+
return findSolanaV14(environment, normalizeNetwork(network)) !== undefined;
|
|
96
|
+
}
|
|
97
|
+
// ── The resolver ─────────────────────────────────────────────────────────────
|
|
98
|
+
/**
|
|
99
|
+
* Resolve the Solana deployment the SDK should use. The single source of truth
|
|
100
|
+
* for Solana environment + protocol-version selection.
|
|
101
|
+
*
|
|
102
|
+
* @throws UnsupportedSolanaDevNetworkError dev asked for a non-devnet cluster
|
|
103
|
+
* @throws SolanaV12UnavailableError explicit v1.2 (none exists on Solana)
|
|
104
|
+
* @throws SolanaVersionUnavailableError explicit v1.4 not deployed here
|
|
105
|
+
* @throws NoSolanaDeploymentError auto, but no v1.4 for this env+network
|
|
106
|
+
*/
|
|
107
|
+
export function resolveSolanaDeployment(options) {
|
|
108
|
+
const { environment } = options;
|
|
109
|
+
if (environment !== "dev" && environment !== "prod") {
|
|
110
|
+
throw new DeploymentResolverError(`Unknown environment "${String(environment)}"; use "dev" or "prod".`);
|
|
111
|
+
}
|
|
112
|
+
const network = normalizeNetwork(options.network);
|
|
113
|
+
const requested = options.version ?? "auto";
|
|
114
|
+
// Development is restricted to devnet, whatever version is asked for. Reject
|
|
115
|
+
// any other development cluster rather than silently resolving mainnet.
|
|
116
|
+
if (environment === "dev" && !SOLANA_DEV_NETWORKS.includes(network)) {
|
|
117
|
+
throw new UnsupportedSolanaDevNetworkError(options.network);
|
|
118
|
+
}
|
|
119
|
+
const v14 = findSolanaV14(environment, network);
|
|
120
|
+
const asV14 = (d) => ({
|
|
121
|
+
version: "v1.4",
|
|
122
|
+
environment,
|
|
123
|
+
network: d.network,
|
|
124
|
+
programId: d.programId,
|
|
125
|
+
deployment: d,
|
|
126
|
+
});
|
|
127
|
+
switch (requested) {
|
|
128
|
+
case "v1.4":
|
|
129
|
+
if (v14)
|
|
130
|
+
return asV14(v14);
|
|
131
|
+
throw new SolanaVersionUnavailableError("v1.4", environment, options.network);
|
|
132
|
+
case "v1.2":
|
|
133
|
+
// No Solana v1.2 deployment exists — there is nothing to return.
|
|
134
|
+
throw new SolanaV12UnavailableError();
|
|
135
|
+
case "auto":
|
|
136
|
+
if (v14)
|
|
137
|
+
return asV14(v14);
|
|
138
|
+
throw new NoSolanaDeploymentError(environment, options.network);
|
|
139
|
+
default:
|
|
140
|
+
throw new DeploymentResolverError(`Unknown version "${String(requested)}"; use "v1.2", "v1.4" or "auto".`);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
//# sourceMappingURL=solanaDeploymentResolver.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"solanaDeploymentResolver.js","sourceRoot":"","sources":["../src/solanaDeploymentResolver.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import type { SdkEnvironment } from "./deploymentResolver.js";
|
|
2
|
+
/** Solana clusters the resolver understands. `dev` maps to devnet, `prod` to
|
|
3
|
+
* mainnet-beta. */
|
|
4
|
+
export type SolanaNetwork = "devnet" | "mainnet";
|
|
5
|
+
/** A Solana splitter v1.4 deployment, as recorded by the deploy scripts. */
|
|
6
|
+
export interface SolanaV14Deployment {
|
|
7
|
+
network: SolanaNetwork;
|
|
8
|
+
/** Which SDK environment this deployment belongs to: devnet is the dev
|
|
9
|
+
* target, mainnet is prod. */
|
|
10
|
+
environment: SdkEnvironment;
|
|
11
|
+
splitterVersion: "1.4";
|
|
12
|
+
/** Base58 on-chain program id, from the deploy log's "Canonical program ID
|
|
13
|
+
* confirmed" line. Never hardcoded in resolver logic — read from here. */
|
|
14
|
+
programId: string;
|
|
15
|
+
/** IDL metadata (Anchor), for callers that load the IDL. */
|
|
16
|
+
idl: {
|
|
17
|
+
name: string;
|
|
18
|
+
version: string;
|
|
19
|
+
/** Path of the source IDL artifact in solana-contract, for provenance. */
|
|
20
|
+
artifact: string;
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
/** Where this table came from, so a build can be traced to a commit. */
|
|
24
|
+
export declare const SOLANA_V14_DEPLOYMENTS_SOURCE: {
|
|
25
|
+
readonly repo: "AiFinPay/solana-contract";
|
|
26
|
+
readonly branch: "dev";
|
|
27
|
+
readonly commit: "8a13d10d6210cd37345f7ae6684068bf849e24b1";
|
|
28
|
+
readonly path: "deployments/splitter_v14/";
|
|
29
|
+
};
|
|
30
|
+
/** Solana v1.4 deployments, keyed by cluster. Devnet is dev-only; mainnet is
|
|
31
|
+
* prod-only. Absence of a cluster here means no v1.4 deployment for it. */
|
|
32
|
+
export declare const SOLANA_V14_DEPLOYMENTS: Record<string, SolanaV14Deployment>;
|
|
33
|
+
/** The single development cluster Solana v1.4 supports today. */
|
|
34
|
+
export declare const SOLANA_DEV_NETWORKS: readonly ["devnet"];
|
|
35
|
+
//# sourceMappingURL=solanaV14Deployments.generated.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"solanaV14Deployments.generated.d.ts","sourceRoot":"","sources":["../src/solanaV14Deployments.generated.ts"],"names":[],"mappings":"AA0BA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AAE9D;oBACoB;AACpB,MAAM,MAAM,aAAa,GAAG,QAAQ,GAAG,SAAS,CAAC;AAEjD,4EAA4E;AAC5E,MAAM,WAAW,mBAAmB;IAClC,OAAO,EAAE,aAAa,CAAC;IACvB;mCAC+B;IAC/B,WAAW,EAAE,cAAc,CAAC;IAC5B,eAAe,EAAE,KAAK,CAAC;IACvB;+EAC2E;IAC3E,SAAS,EAAE,MAAM,CAAC;IAClB,4DAA4D;IAC5D,GAAG,EAAE;QACH,IAAI,EAAE,MAAM,CAAC;QACb,OAAO,EAAE,MAAM,CAAC;QAChB,0EAA0E;QAC1E,QAAQ,EAAE,MAAM,CAAC;KAClB,CAAC;CACH;AAED,wEAAwE;AACxE,eAAO,MAAM,6BAA6B;;;;;CAKhC,CAAC;AAEX;4EAC4E;AAC5E,eAAO,MAAM,sBAAsB,EAAE,MAAM,CAAC,MAAM,EAAE,mBAAmB,CAyBtE,CAAC;AAEF,iEAAiE;AACjE,eAAO,MAAM,mBAAmB,qBAAsB,CAAC"}
|