@faremeter/info 0.15.0 → 0.17.0

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.
@@ -2,38 +2,87 @@
2
2
  import t from "tap";
3
3
  import * as evm from "./evm.js";
4
4
  await t.test("basicNetworkLookup", async (t) => {
5
- t.ok(evm.isKnownX402Network("base"));
6
- t.ok(!evm.isKnownX402Network("asdkljas"));
5
+ t.ok(evm.isKnownCAIP2Network("eip155:8453"));
6
+ t.ok(!evm.isKnownCAIP2Network("eip155:999999"));
7
+ t.ok(!evm.isKnownCAIP2Network("base"));
8
+ t.end();
9
+ });
10
+ await t.test("networkConversions", async (t) => {
11
+ await t.test("chainIdToCAIP2", (t) => {
12
+ t.equal(evm.chainIdToCAIP2(8453), "eip155:8453");
13
+ t.equal(evm.chainIdToCAIP2(84532), "eip155:84532");
14
+ t.equal(evm.chainIdToCAIP2(999999), "eip155:999999");
15
+ t.end();
16
+ });
17
+ await t.test("caip2ToChainId", (t) => {
18
+ t.equal(evm.caip2ToChainId("eip155:8453"), 8453);
19
+ t.equal(evm.caip2ToChainId("eip155:84532"), 84532);
20
+ t.equal(evm.caip2ToChainId("invalid"), null);
21
+ t.equal(evm.caip2ToChainId("eip155:"), null);
22
+ t.end();
23
+ });
24
+ await t.test("legacyNameToCAIP2", (t) => {
25
+ t.equal(evm.legacyNameToCAIP2("base"), "eip155:8453");
26
+ t.equal(evm.legacyNameToCAIP2("base-sepolia"), "eip155:84532");
27
+ t.equal(evm.legacyNameToCAIP2("skale-europa-testnet"), "eip155:1444673419");
28
+ t.equal(evm.legacyNameToCAIP2("unknown-network"), null);
29
+ t.end();
30
+ });
31
+ await t.test("caip2ToLegacyName", (t) => {
32
+ t.equal(evm.caip2ToLegacyName("eip155:8453"), "base");
33
+ t.equal(evm.caip2ToLegacyName("eip155:84532"), "base-sepolia");
34
+ t.equal(evm.caip2ToLegacyName("eip155:999999"), null);
35
+ t.end();
36
+ });
37
+ await t.test("normalizeNetworkId", (t) => {
38
+ t.equal(evm.normalizeNetworkId(8453), "eip155:8453");
39
+ t.equal(evm.normalizeNetworkId("base"), "eip155:8453");
40
+ t.equal(evm.normalizeNetworkId("base-sepolia"), "eip155:84532");
41
+ t.equal(evm.normalizeNetworkId("eip155:8453"), "eip155:8453");
42
+ t.equal(evm.normalizeNetworkId("84532"), "eip155:84532");
43
+ t.end();
44
+ });
45
+ t.end();
7
46
  });
8
47
  await t.test("basicAssetLookup", async (t) => {
9
48
  await t.test((t) => {
10
- const info = evm.lookupKnownAsset("base-sepolia", "USDC");
49
+ const info = evm.lookupKnownAsset("eip155:84532", "USDC");
11
50
  if (!info) {
12
51
  throw new Error("failed to lookup known EVM asset");
13
52
  }
14
53
  t.matchOnly(info.address, "0x036cbd53842c5426634e7929541ec2318f3dcf7e");
15
54
  t.matchOnly(info.name, "USDC");
16
- t.matchOnly(info.network, "base-sepolia");
55
+ t.matchOnly(info.network, "eip155:84532");
17
56
  t.equal(info.forwarder, undefined);
18
57
  t.equal(info.forwarderName, undefined);
19
58
  t.equal(info.forwarderVersion, undefined);
20
59
  t.end();
21
60
  });
61
+ await t.test("lookup by legacy name", (t) => {
62
+ const info = evm.lookupKnownAsset("base-sepolia", "USDC");
63
+ if (!info) {
64
+ throw new Error("failed to lookup known EVM asset by legacy name");
65
+ }
66
+ t.matchOnly(info.address, "0x036cbd53842c5426634e7929541ec2318f3dcf7e");
67
+ t.matchOnly(info.name, "USDC");
68
+ t.matchOnly(info.network, "eip155:84532");
69
+ t.end();
70
+ });
22
71
  await t.test((t) => {
23
- const info = evm.lookupKnownAsset("skale-europa-testnet", "USDC");
72
+ const info = evm.lookupKnownAsset("eip155:1444673419", "USDC");
24
73
  if (!info) {
25
74
  throw new Error("failed to lookup known EVM asset");
26
75
  }
27
76
  t.matchOnly(info.address, "0x9eAb55199f4481eCD7659540A17Af618766b07C4");
28
77
  t.matchOnly(info.name, "USDC");
29
- t.matchOnly(info.network, "skale-europa-testnet");
78
+ t.matchOnly(info.network, "eip155:1444673419");
30
79
  t.matchOnly(info.forwarder, "0x7779B0d1766e6305E5f8081E3C0CDF58FcA24330");
31
80
  t.matchOnly(info.forwarderName, "USDC Forwarder");
32
81
  t.matchOnly(info.forwarderVersion, "1");
33
82
  t.end();
34
83
  });
35
84
  await t.test((t) => {
36
- const info = evm.lookupKnownAsset("alsdkjaklsdj", "asldkjasd");
85
+ const info = evm.lookupKnownAsset("eip155:999999", "asldkjasd");
37
86
  t.matchOnly(info, undefined);
38
87
  t.end();
39
88
  });
@@ -42,21 +91,21 @@ await t.test("basicAssetLookup", async (t) => {
42
91
  t.ok(!evm.isKnownAsset("notarealtoken"));
43
92
  t.end();
44
93
  });
45
- await t.test((t) => {
94
+ await t.test("lookup by chain ID number", (t) => {
46
95
  const info = evm.lookupKnownAsset(84532, "USDC");
47
96
  if (!info) {
48
97
  throw new Error("failed to lookup known EVM asset");
49
98
  }
50
99
  t.matchOnly(info.address, "0x036cbd53842c5426634e7929541ec2318f3dcf7e");
51
100
  t.matchOnly(info.name, "USDC");
52
- t.matchOnly(info.network, "base-sepolia");
101
+ t.matchOnly(info.network, "eip155:84532");
53
102
  t.end();
54
103
  });
55
104
  t.end();
56
105
  });
57
106
  await t.test("basicChainLookup", async (t) => {
58
- t.matchOnly(evm.lookupX402Network(8453), "base");
59
- t.matchOnly(evm.lookupX402Network(84532), "base-sepolia");
107
+ t.matchOnly(evm.lookupX402Network(8453), "eip155:8453");
108
+ t.matchOnly(evm.lookupX402Network(84532), "eip155:84532");
60
109
  t.matchOnly(evm.lookupX402Network(8675309), "eip155:8675309");
61
110
  t.end();
62
111
  });
@@ -1,3 +1,35 @@
1
- export * as solana from "./solana.js";
2
- export * as evm from "./evm.js";
1
+ /**
2
+ * @title Info Package
3
+ * @sidebarTitle Info
4
+ * @description Network and asset information utilities for EVM and Solana chains
5
+ * @packageDocumentation
6
+ */
7
+ import * as solana from "./solana.js";
8
+ import * as evm from "./evm.js";
9
+ /**
10
+ * @title Solana Network Info
11
+ * @sidebarTitle Info / Solana
12
+ * @description Solana cluster, network ID, and SPL token utilities
13
+ */
14
+ export { solana };
15
+ /**
16
+ * @title EVM Network Info
17
+ * @sidebarTitle Info / EVM
18
+ * @description EVM chain ID, CAIP-2, and ERC-20 token utilities
19
+ */
20
+ export { evm };
21
+ /**
22
+ * Normalize a legacy network identifier to CAIP-2 format.
23
+ * Handles both EVM and Solana networks.
24
+ * Returns the input unchanged if no mapping exists (may already be CAIP-2
25
+ * or an unknown network).
26
+ */
27
+ export declare function normalizeNetworkId(network: string): string;
28
+ /**
29
+ * Translate a CAIP-2 network identifier to legacy format.
30
+ * Handles both EVM and Solana networks.
31
+ * Returns the input unchanged if no mapping exists (may not be a known
32
+ * CAIP-2 network, or may already be legacy).
33
+ */
34
+ export declare function translateNetworkToLegacy(network: string): string;
3
35
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,MAAM,UAAU,CAAC;AACnC,OAAO,KAAK,GAAG,MAAM,OAAO,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,KAAK,MAAM,MAAM,UAAU,CAAC;AACnC,OAAO,KAAK,GAAG,MAAM,OAAO,CAAC;AAE7B;;;;GAIG;AACH,OAAO,EAAE,MAAM,EAAE,CAAC;AAClB;;;;GAIG;AACH,OAAO,EAAE,GAAG,EAAE,CAAC;AAEf;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAU1D;AAED;;;;;GAKG;AACH,wBAAgB,wBAAwB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAShE"}
package/dist/src/index.js CHANGED
@@ -1,2 +1,55 @@
1
- export * as solana from "./solana.js";
2
- export * as evm from "./evm.js";
1
+ /**
2
+ * @title Info Package
3
+ * @sidebarTitle Info
4
+ * @description Network and asset information utilities for EVM and Solana chains
5
+ * @packageDocumentation
6
+ */
7
+ import * as solana from "./solana.js";
8
+ import * as evm from "./evm.js";
9
+ /**
10
+ * @title Solana Network Info
11
+ * @sidebarTitle Info / Solana
12
+ * @description Solana cluster, network ID, and SPL token utilities
13
+ */
14
+ export { solana };
15
+ /**
16
+ * @title EVM Network Info
17
+ * @sidebarTitle Info / EVM
18
+ * @description EVM chain ID, CAIP-2, and ERC-20 token utilities
19
+ */
20
+ export { evm };
21
+ /**
22
+ * Normalize a legacy network identifier to CAIP-2 format.
23
+ * Handles both EVM and Solana networks.
24
+ * Returns the input unchanged if no mapping exists (may already be CAIP-2
25
+ * or an unknown network).
26
+ */
27
+ export function normalizeNetworkId(network) {
28
+ if (network.startsWith("eip155:"))
29
+ return network;
30
+ const evmCaip2 = evm.legacyNameToCAIP2(network);
31
+ if (evmCaip2)
32
+ return evmCaip2;
33
+ if (network.startsWith("solana:"))
34
+ return network;
35
+ const solanaNetwork = solana.legacyNetworkIdToCAIP2(network);
36
+ if (solanaNetwork)
37
+ return solanaNetwork.caip2;
38
+ return network;
39
+ }
40
+ /**
41
+ * Translate a CAIP-2 network identifier to legacy format.
42
+ * Handles both EVM and Solana networks.
43
+ * Returns the input unchanged if no mapping exists (may not be a known
44
+ * CAIP-2 network, or may already be legacy).
45
+ */
46
+ export function translateNetworkToLegacy(network) {
47
+ const evmLegacy = evm.caip2ToLegacyName(network);
48
+ if (evmLegacy)
49
+ return evmLegacy;
50
+ const solanaLegacy = solana.caip2ToLegacyNetworkIds(network);
51
+ const firstSolanaLegacy = solanaLegacy?.[0];
52
+ if (firstSolanaLegacy)
53
+ return firstSolanaLegacy;
54
+ return network;
55
+ }
@@ -1,10 +1,76 @@
1
1
  import { type UnitInput } from "./common.js";
2
- import { Base58Address } from "@faremeter/types/solana";
3
- declare const knownClusters: readonly ["devnet", "testnet", "mainnet-beta"];
4
- type knownClusters = typeof knownClusters;
5
- export type KnownCluster = (typeof knownClusters)[number];
2
+ import { type SolanaCluster, type SolanaCAIP2Network, Base58Address, isSolanaCluster, isSolanaCAIP2Network, isSolanaCAIP2NetworkString, createSolanaNetwork } from "@faremeter/types/solana";
3
+ export type { SolanaCluster, SolanaCAIP2Network };
4
+ export type KnownCluster = SolanaCluster;
5
+ export { isSolanaCluster, isSolanaCAIP2Network, isSolanaCAIP2NetworkString, createSolanaNetwork, };
6
6
  export declare function isKnownCluster(c: string): c is KnownCluster;
7
- export declare const lookupX402Network: (network: string) => string[];
7
+ export declare const SOLANA_MAINNET_BETA: SolanaCAIP2Network;
8
+ export declare const SOLANA_DEVNET: SolanaCAIP2Network;
9
+ export declare const SOLANA_TESTNET: SolanaCAIP2Network;
10
+ /**
11
+ * Type guard that checks if a string is a known Solana CAIP-2 network.
12
+ *
13
+ * @param n - The string to check
14
+ * @returns True if the string is a known Solana CAIP-2 network identifier
15
+ */
16
+ export declare function isKnownSolanaCAIP2Network(n: string): boolean;
17
+ /**
18
+ * Converts a Solana cluster name to a SolanaCAIP2Network object.
19
+ *
20
+ * @param cluster - The Solana cluster name
21
+ * @returns The corresponding SolanaCAIP2Network object
22
+ * @throws Error if the cluster is unknown
23
+ */
24
+ export declare function clusterToCAIP2(cluster: SolanaCluster): SolanaCAIP2Network;
25
+ /**
26
+ * Converts a CAIP-2 network identifier to Solana cluster name.
27
+ *
28
+ * @param caip2 - The CAIP-2 network identifier string
29
+ * @returns The cluster name, or null if not a known Solana network
30
+ */
31
+ export declare function caip2ToCluster(caip2: string): SolanaCluster | null;
32
+ /**
33
+ * Converts a legacy Solana network ID to a SolanaCAIP2Network object.
34
+ *
35
+ * @param legacy - Legacy network identifier (e.g., "solana-mainnet-beta")
36
+ * @returns The SolanaCAIP2Network object, or null if unknown
37
+ */
38
+ export declare function legacyNetworkIdToCAIP2(legacy: string): SolanaCAIP2Network | null;
39
+ /**
40
+ * Converts a CAIP-2 network identifier to legacy Solana network IDs.
41
+ *
42
+ * @param caip2 - The CAIP-2 network identifier string
43
+ * @returns Array of legacy network IDs, or null if unknown
44
+ */
45
+ export declare function caip2ToLegacyNetworkIds(caip2: string): readonly string[] | null;
46
+ /**
47
+ * Normalizes a Solana network identifier to CAIP-2 format string.
48
+ *
49
+ * Accepts cluster names, legacy IDs, or CAIP-2 identifiers.
50
+ * Returns the input unchanged if no mapping exists.
51
+ *
52
+ * @param network - The network identifier in any supported format
53
+ * @returns The CAIP-2 network identifier string, or the original string if unrecognized
54
+ */
55
+ export declare function normalizeNetworkId(network: string): string;
56
+ /**
57
+ * Looks up the x402 network identifier for a Solana cluster.
58
+ *
59
+ * Accepts a cluster name, CAIP-2 identifier string, legacy network ID,
60
+ * or an existing SolanaCAIP2Network object.
61
+ *
62
+ * @param network - Cluster name, CAIP-2 ID, legacy network ID, or SolanaCAIP2Network object
63
+ * @returns A SolanaCAIP2Network object
64
+ * @throws Error if the network is unknown or invalid
65
+ */
66
+ export declare function lookupX402Network(network: string | SolanaCAIP2Network): SolanaCAIP2Network;
67
+ /**
68
+ * Gets the v1 legacy network IDs for a Solana cluster.
69
+ *
70
+ * @param cluster - The Solana cluster name
71
+ * @returns Array of legacy network IDs for v1 compatibility
72
+ */
73
+ export declare function getV1NetworkIds(cluster: KnownCluster): string[];
8
74
  declare const knownSPLTokens: {
9
75
  readonly USDC: {
10
76
  readonly cluster: {
@@ -19,12 +85,25 @@ declare const knownSPLTokens: {
19
85
  };
20
86
  };
21
87
  export type KnownSPLToken = keyof typeof knownSPLTokens;
88
+ /**
89
+ * Looks up SPL token information by cluster and token name.
90
+ *
91
+ * @param cluster - The Solana cluster
92
+ * @param name - The known SPL token name (e.g., "USDC")
93
+ * @returns Token information including address, or undefined if not found
94
+ */
22
95
  export declare function lookupKnownSPLToken(cluster: KnownCluster, name: KnownSPLToken): {
23
- cluster: "devnet" | "testnet" | "mainnet-beta";
96
+ cluster: "mainnet-beta" | "devnet" | "testnet";
24
97
  name: "USDC";
25
98
  toUnit: (v: UnitInput) => string;
26
99
  address: Base58Address;
27
100
  } | undefined;
101
+ /**
102
+ * Type guard that checks if a string is a known SPL token name.
103
+ *
104
+ * @param splToken - The string to check
105
+ * @returns True if the string is a known SPL token
106
+ */
28
107
  export declare function isKnownSPLToken(splToken: string): splToken is KnownSPLToken;
29
108
  export type x402ExactArgs = {
30
109
  network: KnownCluster;
@@ -32,16 +111,24 @@ export type x402ExactArgs = {
32
111
  amount: UnitInput;
33
112
  payTo: Base58Address;
34
113
  };
114
+ /**
115
+ * Creates x402 exact payment requirements for Solana.
116
+ *
117
+ * Returns multiple requirements for v1 compatibility (one per legacy network ID).
118
+ *
119
+ * @param args - Payment configuration including network, asset, amount, and payTo
120
+ * @returns Array of x402 payment requirements
121
+ */
35
122
  export declare function x402Exact(args: x402ExactArgs): Partial<{
36
123
  scheme: string;
37
124
  network: string;
38
125
  maxAmountRequired: string;
39
126
  resource: string;
40
127
  description: string;
41
- mimeType: string;
42
128
  payTo: string;
43
129
  maxTimeoutSeconds: number;
44
130
  asset: string;
131
+ mimeType?: string;
45
132
  outputSchema?: object;
46
133
  extra?: object;
47
134
  }>[];
@@ -51,18 +138,25 @@ export type xSolanaSettlementArgs = {
51
138
  amount: UnitInput;
52
139
  payTo: Base58Address;
53
140
  };
141
+ /**
142
+ * Creates x-solana-settlement payment requirements.
143
+ *
144
+ * Supports both SPL tokens and native SOL.
145
+ *
146
+ * @param args - Payment configuration including network, asset, amount, and payTo
147
+ * @returns x402 payment requirement for the settlement scheme
148
+ */
54
149
  export declare function xSolanaSettlement(args: xSolanaSettlementArgs): Partial<{
55
150
  scheme: string;
56
151
  network: string;
57
152
  maxAmountRequired: string;
58
153
  resource: string;
59
154
  description: string;
60
- mimeType: string;
61
155
  payTo: string;
62
156
  maxTimeoutSeconds: number;
63
157
  asset: string;
158
+ mimeType?: string;
64
159
  outputSchema?: object;
65
160
  extra?: object;
66
161
  }>;
67
- export {};
68
162
  //# sourceMappingURL=solana.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"solana.d.ts","sourceRoot":"","sources":["../../src/solana.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,SAAS,EAAqC,MAAM,UAAU,CAAC;AAC7E,OAAO,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AAExD,QAAA,MAAM,aAAa,gDAAiD,CAAC;AACrE,KAAK,aAAa,GAAG,OAAO,aAAa,CAAC;AAC1C,MAAM,MAAM,YAAY,GAAG,CAAC,OAAO,aAAa,CAAC,CAAC,MAAM,CAAC,CAAC;AAE1D,wBAAgB,cAAc,CAAC,CAAC,EAAE,MAAM,GAAG,CAAC,IAAI,YAAY,CAE3D;AAED,eAAO,MAAM,iBAAiB,GAAI,SAAS,MAAM,aAQhD,CAAC;AAOF,QAAA,MAAM,cAAc;;;;;;;;;;6BAUJ,SAAS;;CAEwB,CAAC;AAClD,MAAM,MAAM,aAAa,GAAG,MAAM,OAAO,cAAc,CAAC;AAExD,wBAAgB,mBAAmB,CACjC,OAAO,EAAE,YAAY,EACrB,IAAI,EAAE,aAAa;;;gBApBP,SAAS,KAAK,MAAM;aADiB,aAAa;cAyC/D;AAED,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,QAAQ,IAAI,aAAa,CAE3E;AAED,MAAM,MAAM,aAAa,GAAG;IAC1B,OAAO,EAAE,YAAY,CAAC;IACtB,KAAK,EAAE,aAAa,CAAC;IACrB,MAAM,EAAE,SAAS,CAAC;IAClB,KAAK,EAAE,aAAa,CAAC;CACtB,CAAC;AAEF,wBAAgB,SAAS,CAAC,IAAI,EAAE,aAAa;;;;;;;;;;;;KAqB5C;AAED,MAAM,MAAM,qBAAqB,GAAG;IAClC,OAAO,EAAE,YAAY,CAAC;IACtB,KAAK,EAAE,aAAa,GAAG,KAAK,CAAC;IAC7B,MAAM,EAAE,SAAS,CAAC;IAClB,KAAK,EAAE,aAAa,CAAC;CACtB,CAAC;AAEF,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,qBAAqB;;;;;;;;;;;;GA2B5D"}
1
+ {"version":3,"file":"solana.d.ts","sourceRoot":"","sources":["../../src/solana.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,SAAS,EAAqC,MAAM,UAAU,CAAC;AAC7E,OAAO,EACL,KAAK,aAAa,EAClB,KAAK,kBAAkB,EACvB,aAAa,EACb,eAAe,EACf,oBAAoB,EACpB,0BAA0B,EAC1B,mBAAmB,EACpB,MAAM,yBAAyB,CAAC;AAEjC,YAAY,EAAE,aAAa,EAAE,kBAAkB,EAAE,CAAC;AAElD,MAAM,MAAM,YAAY,GAAG,aAAa,CAAC;AAEzC,OAAO,EACL,eAAe,EACf,oBAAoB,EACpB,0BAA0B,EAC1B,mBAAmB,GACpB,CAAC;AAEF,wBAAgB,cAAc,CAAC,CAAC,EAAE,MAAM,GAAG,CAAC,IAAI,YAAY,CAE3D;AAED,eAAO,MAAM,mBAAmB,oBAG/B,CAAC;AAEF,eAAO,MAAM,aAAa,oBAGzB,CAAC;AAEF,eAAO,MAAM,cAAc,oBAG1B,CAAC;AAwBF;;;;;GAKG;AACH,wBAAgB,yBAAyB,CAAC,CAAC,EAAE,MAAM,GAAG,OAAO,CAE5D;AAgBD;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,aAAa,GAAG,kBAAkB,CAMzE;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,aAAa,GAAG,IAAI,CAMlE;AAED;;;;;GAKG;AACH,wBAAgB,sBAAsB,CACpC,MAAM,EAAE,MAAM,GACb,kBAAkB,GAAG,IAAI,CAE3B;AAED;;;;;GAKG;AACH,wBAAgB,uBAAuB,CACrC,KAAK,EAAE,MAAM,GACZ,SAAS,MAAM,EAAE,GAAG,IAAI,CAM1B;AAED;;;;;;;;GAQG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAe1D;AAED;;;;;;;;;GASG;AACH,wBAAgB,iBAAiB,CAC/B,OAAO,EAAE,MAAM,GAAG,kBAAkB,GACnC,kBAAkB,CAuBpB;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,YAAY,GAAG,MAAM,EAAE,CAI/D;AAOD,QAAA,MAAM,cAAc;;;;;;;;;;6BAUJ,SAAS;;CAEwB,CAAC;AAElD,MAAM,MAAM,aAAa,GAAG,MAAM,OAAO,cAAc,CAAC;AAExD;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CACjC,OAAO,EAAE,YAAY,EACrB,IAAI,EAAE,aAAa;;;gBA5BP,SAAS,KAAK,MAAM;aADiB,aAAa;cAiD/D;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,QAAQ,IAAI,aAAa,CAE3E;AAED,MAAM,MAAM,aAAa,GAAG;IAC1B,OAAO,EAAE,YAAY,CAAC;IACtB,KAAK,EAAE,aAAa,CAAC;IACrB,MAAM,EAAE,SAAS,CAAC;IAClB,KAAK,EAAE,aAAa,CAAC;CACtB,CAAC;AAEF;;;;;;;GAOG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,aAAa;;;;;;;;;;;;KAqB5C;AAED,MAAM,MAAM,qBAAqB,GAAG;IAClC,OAAO,EAAE,YAAY,CAAC;IACtB,KAAK,EAAE,aAAa,GAAG,KAAK,CAAC;IAC7B,MAAM,EAAE,SAAS,CAAC;IAClB,KAAK,EAAE,aAAa,CAAC;CACtB,CAAC;AAEF;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,qBAAqB;;;;;;;;;;;;GA2B5D"}
@@ -1,16 +1,157 @@
1
1
  import { addX402PaymentRequirementDefaults } from "./common.js";
2
- import { Base58Address } from "@faremeter/types/solana";
3
- const knownClusters = ["devnet", "testnet", "mainnet-beta"];
2
+ import { Base58Address, isSolanaCluster, isSolanaCAIP2Network, isSolanaCAIP2NetworkString, createSolanaNetwork, } from "@faremeter/types/solana";
3
+ export { isSolanaCluster, isSolanaCAIP2Network, isSolanaCAIP2NetworkString, createSolanaNetwork, };
4
4
  export function isKnownCluster(c) {
5
- return knownClusters.includes(c);
5
+ return isSolanaCluster(c);
6
6
  }
7
- export const lookupX402Network = (network) => {
8
- const networks = [`solana-${network}`];
9
- if (network === "mainnet-beta") {
10
- networks.push("solana");
11
- }
12
- return networks;
7
+ export const SOLANA_MAINNET_BETA = createSolanaNetwork("solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp", "mainnet-beta");
8
+ export const SOLANA_DEVNET = createSolanaNetwork("solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1", "devnet");
9
+ export const SOLANA_TESTNET = createSolanaNetwork("solana:4uhcVJyU9pJkvQyS88uRDiswHXSCkY3z", "testnet");
10
+ const knownSolanaNetworks = {
11
+ [SOLANA_MAINNET_BETA.caip2]: {
12
+ network: SOLANA_MAINNET_BETA,
13
+ legacyNetworkIds: ["solana-mainnet-beta", "solana"],
14
+ },
15
+ [SOLANA_DEVNET.caip2]: {
16
+ network: SOLANA_DEVNET,
17
+ legacyNetworkIds: ["solana-devnet"],
18
+ },
19
+ [SOLANA_TESTNET.caip2]: {
20
+ network: SOLANA_TESTNET,
21
+ legacyNetworkIds: ["solana-testnet"],
22
+ },
13
23
  };
24
+ /**
25
+ * Type guard that checks if a string is a known Solana CAIP-2 network.
26
+ *
27
+ * @param n - The string to check
28
+ * @returns True if the string is a known Solana CAIP-2 network identifier
29
+ */
30
+ export function isKnownSolanaCAIP2Network(n) {
31
+ return n in knownSolanaNetworks;
32
+ }
33
+ const clusterToNetworkMap = new Map(Object.values(knownSolanaNetworks).map((info) => [
34
+ info.network.name,
35
+ info.network,
36
+ ]));
37
+ const legacyNetworkIdToNetworkMap = new Map();
38
+ for (const info of Object.values(knownSolanaNetworks)) {
39
+ for (const legacyId of info.legacyNetworkIds) {
40
+ legacyNetworkIdToNetworkMap.set(legacyId, info.network);
41
+ }
42
+ }
43
+ /**
44
+ * Converts a Solana cluster name to a SolanaCAIP2Network object.
45
+ *
46
+ * @param cluster - The Solana cluster name
47
+ * @returns The corresponding SolanaCAIP2Network object
48
+ * @throws Error if the cluster is unknown
49
+ */
50
+ export function clusterToCAIP2(cluster) {
51
+ const network = clusterToNetworkMap.get(cluster);
52
+ if (!network) {
53
+ throw new Error(`Unknown Solana cluster: ${cluster}`);
54
+ }
55
+ return network;
56
+ }
57
+ /**
58
+ * Converts a CAIP-2 network identifier to Solana cluster name.
59
+ *
60
+ * @param caip2 - The CAIP-2 network identifier string
61
+ * @returns The cluster name, or null if not a known Solana network
62
+ */
63
+ export function caip2ToCluster(caip2) {
64
+ const info = knownSolanaNetworks[caip2];
65
+ if (!info) {
66
+ return null;
67
+ }
68
+ return info.network.name;
69
+ }
70
+ /**
71
+ * Converts a legacy Solana network ID to a SolanaCAIP2Network object.
72
+ *
73
+ * @param legacy - Legacy network identifier (e.g., "solana-mainnet-beta")
74
+ * @returns The SolanaCAIP2Network object, or null if unknown
75
+ */
76
+ export function legacyNetworkIdToCAIP2(legacy) {
77
+ return legacyNetworkIdToNetworkMap.get(legacy) ?? null;
78
+ }
79
+ /**
80
+ * Converts a CAIP-2 network identifier to legacy Solana network IDs.
81
+ *
82
+ * @param caip2 - The CAIP-2 network identifier string
83
+ * @returns Array of legacy network IDs, or null if unknown
84
+ */
85
+ export function caip2ToLegacyNetworkIds(caip2) {
86
+ const info = knownSolanaNetworks[caip2];
87
+ if (!info) {
88
+ return null;
89
+ }
90
+ return info.legacyNetworkIds;
91
+ }
92
+ /**
93
+ * Normalizes a Solana network identifier to CAIP-2 format string.
94
+ *
95
+ * Accepts cluster names, legacy IDs, or CAIP-2 identifiers.
96
+ * Returns the input unchanged if no mapping exists.
97
+ *
98
+ * @param network - The network identifier in any supported format
99
+ * @returns The CAIP-2 network identifier string, or the original string if unrecognized
100
+ */
101
+ export function normalizeNetworkId(network) {
102
+ if (isSolanaCAIP2NetworkString(network)) {
103
+ return network;
104
+ }
105
+ if (isSolanaCluster(network)) {
106
+ return clusterToCAIP2(network).caip2;
107
+ }
108
+ const networkObj = legacyNetworkIdToCAIP2(network);
109
+ if (networkObj) {
110
+ return networkObj.caip2;
111
+ }
112
+ return network;
113
+ }
114
+ /**
115
+ * Looks up the x402 network identifier for a Solana cluster.
116
+ *
117
+ * Accepts a cluster name, CAIP-2 identifier string, legacy network ID,
118
+ * or an existing SolanaCAIP2Network object.
119
+ *
120
+ * @param network - Cluster name, CAIP-2 ID, legacy network ID, or SolanaCAIP2Network object
121
+ * @returns A SolanaCAIP2Network object
122
+ * @throws Error if the network is unknown or invalid
123
+ */
124
+ export function lookupX402Network(network) {
125
+ if (isSolanaCAIP2Network(network)) {
126
+ return network;
127
+ }
128
+ if (isSolanaCluster(network)) {
129
+ return clusterToCAIP2(network);
130
+ }
131
+ if (isSolanaCAIP2NetworkString(network)) {
132
+ const known = knownSolanaNetworks[network];
133
+ if (known) {
134
+ return known.network;
135
+ }
136
+ return createSolanaNetwork(network);
137
+ }
138
+ const networkObj = legacyNetworkIdToCAIP2(network);
139
+ if (networkObj) {
140
+ return networkObj;
141
+ }
142
+ throw new Error(`Unknown Solana network: ${network}`);
143
+ }
144
+ /**
145
+ * Gets the v1 legacy network IDs for a Solana cluster.
146
+ *
147
+ * @param cluster - The Solana cluster name
148
+ * @returns Array of legacy network IDs for v1 compatibility
149
+ */
150
+ export function getV1NetworkIds(cluster) {
151
+ const network = clusterToCAIP2(cluster);
152
+ const legacyIds = caip2ToLegacyNetworkIds(network.caip2) ?? [];
153
+ return [...legacyIds];
154
+ }
14
155
  const knownSPLTokens = {
15
156
  USDC: {
16
157
  cluster: {
@@ -24,6 +165,13 @@ const knownSPLTokens = {
24
165
  toUnit: (v) => v.toString(),
25
166
  },
26
167
  };
168
+ /**
169
+ * Looks up SPL token information by cluster and token name.
170
+ *
171
+ * @param cluster - The Solana cluster
172
+ * @param name - The known SPL token name (e.g., "USDC")
173
+ * @returns Token information including address, or undefined if not found
174
+ */
27
175
  export function lookupKnownSPLToken(cluster, name) {
28
176
  const splTokenInfo = knownSPLTokens[name];
29
177
  if (!splTokenInfo) {
@@ -40,28 +188,50 @@ export function lookupKnownSPLToken(cluster, name) {
40
188
  toUnit: splTokenInfo.toUnit,
41
189
  };
42
190
  }
191
+ /**
192
+ * Type guard that checks if a string is a known SPL token name.
193
+ *
194
+ * @param splToken - The string to check
195
+ * @returns True if the string is a known SPL token
196
+ */
43
197
  export function isKnownSPLToken(splToken) {
44
198
  return splToken in knownSPLTokens;
45
199
  }
200
+ /**
201
+ * Creates x402 exact payment requirements for Solana.
202
+ *
203
+ * Returns multiple requirements for v1 compatibility (one per legacy network ID).
204
+ *
205
+ * @param args - Payment configuration including network, asset, amount, and payTo
206
+ * @returns Array of x402 payment requirements
207
+ */
46
208
  export function x402Exact(args) {
47
209
  const tokenInfo = lookupKnownSPLToken(args.network, args.asset);
48
210
  if (!tokenInfo) {
49
211
  throw new Error(`couldn't look up token '${args.asset}' on Solana cluster`);
50
212
  }
51
- const networks = lookupX402Network(args.network);
213
+ const networks = getV1NetworkIds(args.network);
52
214
  const req = networks.map((network) => addX402PaymentRequirementDefaults({
53
215
  scheme: "exact",
54
216
  network,
55
217
  maxAmountRequired: tokenInfo.toUnit(args.amount),
56
218
  payTo: args.payTo,
57
219
  asset: tokenInfo.address,
58
- maxTimeoutSeconds: 60, // from coinbase/x402's middleware defaults
220
+ maxTimeoutSeconds: 60,
59
221
  }));
60
222
  return req;
61
223
  }
224
+ /**
225
+ * Creates x-solana-settlement payment requirements.
226
+ *
227
+ * Supports both SPL tokens and native SOL.
228
+ *
229
+ * @param args - Payment configuration including network, asset, amount, and payTo
230
+ * @returns x402 payment requirement for the settlement scheme
231
+ */
62
232
  export function xSolanaSettlement(args) {
63
233
  let tokenInfo;
64
- // Special-case this, because it's not an SPL Token.
234
+ // Special-case SOL, because it is not an SPL Token.
65
235
  if (args.asset === "sol") {
66
236
  tokenInfo = {
67
237
  address: "sol",
@@ -80,7 +250,7 @@ export function xSolanaSettlement(args) {
80
250
  maxAmountRequired: tokenInfo.toUnit(args.amount),
81
251
  payTo: args.payTo,
82
252
  asset: tokenInfo.address,
83
- maxTimeoutSeconds: 60, // from coinbase/x402's middleware defaults
253
+ maxTimeoutSeconds: 60,
84
254
  });
85
255
  return req;
86
256
  }