@molpha/sdk 0.2.0-dev-20261001084453 → 0.2.0-dev-20261002062009

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/README.md CHANGED
@@ -50,7 +50,9 @@ message = keccak256(
50
50
  )
51
51
  ```
52
52
 
53
- `attestationMessageHash` / `attestationMessageHashFromResult` recompute it client-side.
53
+ The preimage is 141 bytes (32 + 32 + 32 + 4 + 1 + 8 + 32).
54
+
55
+ `attestationMessageHash` / `attestationMessageHashFromAttestation` recompute it client-side.
54
56
 
55
57
  ## Install
56
58
 
@@ -60,15 +62,6 @@ pnpm add @molpha/sdk
60
62
 
61
63
  Runtime dependencies include `@solana/kit`, `@anchor-lang/core`, and `@noble/*`. `bn.js` is an optional peer dependency (used by the Solana / Anchor path).
62
64
 
63
- > **Migration from `@molpha-oracle/sdk`:** The package was renamed to `@molpha/sdk` starting at `0.1.0`. `@molpha-oracle/sdk` is deprecated — update install commands and imports:
64
- >
65
- > ```bash
66
- > pnpm remove @molpha-oracle/sdk
67
- > pnpm add @molpha/sdk
68
- > ```
69
- >
70
- > Replace `@molpha-oracle/sdk` with `@molpha/sdk` in all import paths (including `@molpha/sdk/utils`).
71
-
72
65
  | Import | Use |
73
66
  |---|---|
74
67
  | `@molpha/sdk` | Facade (`MolphaSDK`), `MolphaGateway`, `MolphaSolanaClient`, core hashing (`deriveSourceId`, `attestationMessageHash`, `hashRequestAuth`), EVM/Starknet helpers. Browser-safe; no `fs` in the main entry. |
@@ -108,7 +101,7 @@ const { result, signature, feed } = await sdk.requestAndSubmit({
108
101
  });
109
102
 
110
103
  // The round's identity, for reads and cross-chain verification.
111
- const sourceId = deriveSourceIdString(apiConfig); // === result.sourceId
104
+ const sourceId = deriveSourceIdString(apiConfig); // === result.payload.sourceId
112
105
  ```
113
106
 
114
107
  `requestAndSubmit` requests a threshold-signed attestation from the gateway (against the current on-chain registry version) and submits it to Solana via `submit_attestation` in one call. The first successful submit creates the feed account for `(sourceId, signaturesRequired, submitter)` if it does not already exist.
@@ -223,8 +216,7 @@ import { web3 } from "@anchor-lang/core";
223
216
  import {
224
217
  MolphaSDK,
225
218
  PlanType,
226
- deriveApiConfigHash,
227
- deriveFeedIdString,
219
+ deriveSourceIdString,
228
220
  } from "@molpha/sdk";
229
221
  import { walletFromKeypairFile } from "@molpha/sdk/utils";
230
222
 
@@ -268,6 +260,8 @@ const apiConfig = {
268
260
  const sourceId = deriveSourceIdString(apiConfig); // 64 hex chars, no 0x
269
261
  ```
270
262
 
263
+ The canonical JSON has the fixed key order `url`, `method`, `headers` (sorted by UTF-16 code units, `{}` if empty), `responseParser`, `valueTransform` and, for [tolerance mode](#median-tolerance-mode), a trailing `aggregation`. The key is omitted for exact mode, so existing five-field configs keep their `sourceId`.
264
+
271
265
  The gateway, the Solana program and the EVM/Starknet verifiers all recompute `sourceId` from the same canonical config, so pass the same `apiConfig` (including `{{secret.*}}` placeholders) every time. `signaturesRequired` is **not** part of `sourceId`: on Solana a feed account is keyed by `(sourceId, signaturesRequired, submitter)`, so the same source can be tracked at different quorums.
272
266
 
273
267
  ### 3. Request signed data from the gateway
@@ -282,7 +276,9 @@ const result = await sdk.gateway.requestSignedData({
282
276
 
283
277
  The gateway round uses the current on-chain registry version. Selected verifier nodes independently fetch/recompute the result and sign only if the observed value matches the canonical result.
284
278
 
285
- The returned `DataUpdateResult` includes `sourceId`, the signed value, canonical timestamp, registry version, required quorum, signer bitmap, and aggregate signature. `signaturesRequired` must be at least the protocol's `min_signers` (currently 3) or the chain rejects the submit.
279
+ The returned `Attestation` matches the cross-VM struct (`payload` + `signature`), plus gateway-only `value` (human-readable) and `fresh`. `payload` carries `sourceId`, the signed 32-byte `value`, `canonicalTimestamp`, `registryVersion`, and `signaturesRequired`; `signature` carries the aggregate Schnorr material and `signersBitmap`. `signaturesRequired` must be at least the protocol's `min_signers` (currently 3) or the chain rejects the submit.
280
+
281
+ A gateway response is a coordination result, not proof of settlement or of on-chain verification. Consumers still decide freshness, source, quorum and replay policy.
286
282
 
287
283
  ### 4. Submit on Solana
288
284
 
@@ -290,8 +286,9 @@ The returned `DataUpdateResult` includes `sourceId`, the signed value, canonical
290
286
  const { signature, feed } = await sdk.solana.submitAttestation(result);
291
287
  ```
292
288
 
293
- If the signed 32-byte value is the keccak digest of a longer preimage, provide the
294
- preimage explicitly (up to 256 bytes). The SDK verifies the digest before sending:
289
+ `submit_attestation` takes `{ attestation: { payload, signature }, rawValue, coalitionKey }` plus one read-only `Node` account per signer (ascending signer-bit order, resolved from the registry snapshot the round was signed against). The SDK builds all of it: it fetches the signer `Node` accounts in one batched read, sums their secp256k1 keys into the affine **coalition key** (`computeCoalitionKey`), and checks the program's signer-count bounds before sending. The coalition key is unsigned instruction data that the program checks projectively against its own sum, so a wrong key only fails the transaction. Pass `{ coalitionKey }` to skip the `Node` fetch when you already hold it.
290
+
291
+ If the signed 32-byte value is the keccak digest of a longer preimage, pass `{ rawValue }` (up to 256 bytes). The SDK verifies the digest before sending:
295
292
 
296
293
  ```ts
297
294
  const { signature, feed } = await sdk.solana.submitAttestation(result, { rawValue });
@@ -300,9 +297,13 @@ const { signature, feed } = await sdk.solana.submitAttestation(result, { rawValu
300
297
  Then read the feed this wallet wrote for that source and quorum:
301
298
 
302
299
  ```ts
303
- const feedState = await sdk.solana.readFeed(result.sourceId, signaturesRequired);
300
+ const feedState = await sdk.solana.readFeed(result.payload.sourceId, signaturesRequired);
304
301
  ```
305
302
 
303
+ `FeedAccount.value` is the 32 signed bytes (`valueKind.value`) or their keccak preimage hash (`valueKind.hash`); `submitter` is the wallet that created the feed.
304
+
305
+ The subscription read no longer exposes usage. The program dropped `used_rounds` / `prepaid_usdc` / `price` from `Subscription`; round quota is counted by the gateway's off-chain outbox, so `SubscriptionInfo` carries only `owner`, `planType`, `validUntil`, `maxRounds`, `delegateCount`, `maxDelegates`, `maxSigners`.
306
+
306
307
  ### One-call request + submit
307
308
 
308
309
  ```ts
@@ -352,6 +353,54 @@ refresh the context when the on-chain registry changes. The SDK derives the
352
353
  selection from the on-chain `nodeCount` and refuses a cached node list whose length
353
354
  disagrees with it. The same `context` field is accepted by `requestAndSubmit`.
354
355
 
356
+ ## Median tolerance mode
357
+
358
+ By default every signing node must observe the identical value. For noisy numeric sources
359
+ (prices), add an `aggregation` object and the selected nodes instead exchange signed
360
+ observations, drop stale ones and outliers, and sign the **lower median** of
361
+ `signaturesRequired` surviving observations:
362
+
363
+ ```ts
364
+ const apiConfig = {
365
+ url: "https://api.example.com/price",
366
+ responseParser: "$.price",
367
+ aggregation: {
368
+ mode: "tolerance",
369
+ rule: "median",
370
+ maxDeviationBps: 50, // u32: allowed distance from the lower median, in bps
371
+ maxAgeMs: 2000, // > 0: max observation age in milliseconds
372
+ numeric: { type: "int256", decimals: 8 }, // value = round-half-even(price * 10^8)
373
+ },
374
+ };
375
+
376
+ const { result } = await sdk.requestAndSubmit({ apiConfig, signaturesRequired: 5 });
377
+ ```
378
+
379
+ Rules (the node is the reference; the SDK rejects violations before any request is made, with `AggregationConfigError`):
380
+
381
+ - `aggregation` is part of the `sourceId` and is **omitted** for exact mode. `mode: "exact"` is rejected because it would change the identity.
382
+ - Only `rule: "median"` and `numeric.type: "int256"` are supported. `decimals` is `0..255`, `maxDeviationBps` a u32, `maxAgeMs` a positive integer.
383
+ - Tolerance needs `signaturesRequired >= 3`.
384
+ - The nested object is rebuilt in canonical order (`mode`, `rule`, `maxDeviationBps`, `maxAgeMs`, `numeric{type, decimals}`); extra or reordered keys on your input never reach the hash. For the config above, `sourceId` hashes exactly `{"url":...,"method":"GET","headers":{},"responseParser":"$.price","valueTransform":"","aggregation":{"mode":"tolerance","rule":"median","maxDeviationBps":50,"maxAgeMs":2000,"numeric":{"type":"int256","decimals":8}}}` (pinned against the node's Go test `TestAggregationSourceIdentity`).
385
+ - The signed value is a signed `int256` (two's-complement `bytes32`). For tolerance results `Attestation.value` is rendered from the signed `payload.value` at the source's `decimals`, and `signature.signersBitmap` / signature fields must come from the response, since the nodes choose the final signing set after the observation exchange.
386
+ - The gateway must forward `aggregation` to the nodes. If it derives a different identity, the response's `sourceId` / `configHash` will not match and the SDK throws; a gateway that echoes `aggregation` in its response must echo the requested policy.
387
+
388
+ Helpers for the signed value (mirror the node's `new/tolerance` package):
389
+
390
+ ```ts
391
+ import {
392
+ encodeInt256Decimal, // ("42150.12345678", 8) -> 32-byte Uint8Array, round half to even, bounds-checked
393
+ decodeInt256, // bytes32 (Uint8Array | hex) -> bigint
394
+ formatInt256Decimal, // bytes32 or bigint, decimals -> "42150.12345678" (trailing zeros trimmed)
395
+ encodeInt256, // bigint -> bytes32
396
+ INT256_MIN,
397
+ INT256_MAX,
398
+ } from "@molpha/sdk";
399
+
400
+ const feedState = await sdk.solana.readFeed(result.payload.sourceId, 5);
401
+ const price = formatInt256Decimal(Uint8Array.from(feedState!.value), 8);
402
+ ```
403
+
355
404
  ## Private APIs and encrypted secrets
356
405
 
357
406
  Sources can use private APIs without sending plaintext secrets to the gateway.
@@ -373,7 +422,7 @@ const result = await sdk.gateway.requestSignedData({
373
422
 
374
423
  `MolphaSDK` wires `verifyNodeKeys` to `solana.verifyNodeKeysForPrivateApi`, which authenticates gateway node encryption keys against the on-chain `Node` accounts of the round's registry snapshot (`registry.nodes[index]`) before secrets are encrypted.
375
424
 
376
- Secrets are encrypted into per-node envelopes. The gateway coordinates the round but should not receive plaintext API credentials.
425
+ Secrets are encrypted into per-node envelopes. The gateway coordinates the round but should not receive plaintext API credentials. The encrypted plaintext is the canonical config (including `aggregation`) with secrets substituted.
377
426
 
378
427
  Private API access is still an active security-sensitive surface. Do not treat encrypted secret delivery as production-ready until gateway/node-side test vectors and validation are complete.
379
428
 
@@ -480,21 +529,22 @@ a stateless verifier otherwise accepts a correctly signed attestation forever.
480
529
 
481
530
  The generated object matches the Solidity `IVerifier.Attestation` struct, using viem's
482
531
  primitive types so it passes straight into `readContract` or an ethers `Contract`. Member
483
- order is ABI order (and the signed message's order), so it differs from `DataUpdateResult`:
532
+ order is ABI order (and the signed message's order). The gateway `Attestation` uses the same
533
+ nested shape with lowercase hex strings instead of viem primitives:
484
534
 
485
535
  ```ts
486
536
  attestation:
487
537
  {
488
538
  payload: {
489
- value: `0x${string}`, // bytes32 (result.valuePacked)
539
+ value: `0x${string}`, // bytes32 (Attestation.payload.value)
490
540
  sourceId: `0x${string}`, // bytes32
491
541
  registryVersion: number, // uint32
492
542
  signaturesRequired: number, // uint8
493
- canonicalTimestamp: bigint, // uint64 (result.timestamp)
543
+ canonicalTimestamp: bigint, // uint64
494
544
  },
495
545
  signature: {
496
- signature: `0x${string}`, // bytes32 (result.s)
497
- commitment: `0x${string}`, // address (result.commitmentAddr)
546
+ signature: `0x${string}`, // bytes32 (Attestation.signature.s)
547
+ commitment: `0x${string}`, // address (Attestation.signature.commitmentAddr)
498
548
  signersBitmap: bigint, // uint256
499
549
  },
500
550
  }
@@ -631,7 +681,8 @@ enforces freshness or ordering itself, because a stateless verifier otherwise ac
631
681
  correctly signed attestation forever.
632
682
 
633
683
  The generated object matches the Cairo `Attestation` struct. Member order is Cairo `Serde`
634
- order (and the signed message's order), so it differs from `DataUpdateResult`:
684
+ order (and the signed message's order). The gateway `Attestation` uses the same nested shape
685
+ with lowercase hex strings instead of Cairo felts:
635
686
 
636
687
  ```ts
637
688
  attestation:
@@ -722,7 +773,9 @@ A Molpha attestation is valid only if the verifier can confirm:
722
773
  - the signer bitmap is a subset of the deterministic selection for `(sourceId, registryVersion, canonicalTimestamp)`;
723
774
  - the aggregate Schnorr signature over `attestationMessageHash(...)` is valid;
724
775
  - the timestamp is within the accepted freshness bounds;
725
- - on Solana, the signer `Node` accounts passed as remaining accounts are exactly `registry.nodes[bit]` for every set bit.
776
+ - on Solana, the signer `Node` accounts passed as remaining accounts are exactly `registry.nodes[bit]` for every set bit, and the supplied coalition key matches the sum of their keys.
777
+
778
+ A valid signature does not replace consumer policy: freshness, source, quorum and replay checks remain the consumer's responsibility.
726
779
 
727
780
  Solana verification finalizes feed state via `submit_attestation`. EVM and Starknet verification are stateless and return whether the signed Molpha attestation is valid for the deployed verifier registry.
728
781
 
@@ -738,6 +791,8 @@ import { MOLPHA_IDL, MOLPHA_PROGRAM_ADDRESS } from "@molpha/sdk";
738
791
 
739
792
  Override `idl` and `programId` when targeting another deployment.
740
793
 
794
+ The vendored IDL is `anchor idl build -p molpha` output for `molpha-solana-program` `3d01170` ("Epoch settlements (#47)").
795
+
741
796
  Keep the vendored IDL aligned with the deployed program. Mismatched IDL/program versions can produce invalid account derivations, decoding errors, or failed instruction simulation.
742
797
 
743
798
  ## Standalone clients
@@ -797,31 +852,6 @@ Known limitations:
797
852
 
798
853
  Solana paths such as selection bitmap and `submit_attestation` remaining-accounts resolution are aligned with the Molpha program version vendored in this repo (`MoLFnEbuMS5gWnXNfUMLAYSqRM3eQZKWRzjeMQfqbT3`, not yet deployed).
799
854
 
800
- ## Migrating from 0.1.x
801
-
802
- | Before | After |
803
- |---|---|
804
- | `deriveFeedId(owner, apiConfigHash, sigReq)` / `deriveFeedIdString` | removed — use `deriveSourceId(apiConfig)` / `deriveSourceIdString` |
805
- | `deriveApiConfigHash(apiConfig)` | `deriveSourceId(apiConfig)` (old name kept as a deprecated alias, same bytes) |
806
- | `requestSignedData({ feedId, ... })` | `requestSignedData({ apiConfig, signaturesRequired, ... })` — `sourceId` is derived from `apiConfig` |
807
- | `prepareContext(feedId)` | `prepareContext()` |
808
- | `requestAndSubmit(feedId, opts)` | `requestAndSubmit(opts)` |
809
- | `authMessage(feedId, timestamp)` (sha256) | `hashRequestAuth({ programId, gateway, sourceId, signaturesRequired, timestamp })` (keccak) |
810
- | `endpoints: string[]` | `endpoints: (string \| { url, gatewayAuthority })[]` |
811
- | `submitDataUpdate(result)` | `submitAttestation(result)` (deprecated alias kept); returns `{ signature, feed }` |
812
- | `readFeed(feedId)` | `readFeed(sourceId, signaturesRequired, submitter?)` |
813
- | `result.feedId` / `NodeKeyVerifierArgs.feedId` | `.sourceId` |
814
- | EVM tuple `feedId`, ABI `jobId` | `sourceId` |
815
- | Starknet `feed_id` | `source_id` |
816
- | `buildStarknetVerifierArgs(result)` → `{ dataUpdate, signature }` | `buildStarknetVerifierArgs(result, { maxAge })` → `{ attestation, maxAge }` for `verify(attestation, max_age)` |
817
- | `StarknetDataUpdate` (`signatures_required: u32`) | `StarknetAttestationPayload` (`signatures_required: u8`, `value` first), nested in `StarknetAttestation` |
818
- | Starknet `verify` returns `bool` | returns `(bool, u8)` — decode with `parseStarknetVerifyResult` |
819
- | `buildEvmVerifierArgs(result)` → `{ dataUpdate, signature }` tuples | `buildEvmVerifierArgs(result, { maxAge })` → `{ attestation, maxAge }` for `verify(attestation, maxAge)` |
820
- | `EvmDataUpdateTuple` / `EvmSchnorrSignatureTuple` (positional) | `EvmAttestationPayload` / `EvmSchnorrSignature` objects (`value` first, `signaturesRequired: uint8`, `canonicalTimestamp: bigint`), nested in `EvmAttestation` |
821
- | EVM `verify(DataUpdate, SchnorrSignature)` returns `bool` | `verify(Attestation, uint64)` returns `(bool, uint8)` — decode with `parseEvmVerifyResult` |
822
- | `attestationMessageHash`: `sourceId ‖ u32 rv ‖ u32 sigReq ‖ bitmap ‖ value ‖ u64 ts` | `value ‖ sourceId ‖ u32 rv ‖ u8 sigReq ‖ u64 ts ‖ bitmap` (what nodes sign and every verifier checks) |
823
- | `resolveRegistryIndexForVersion`, `VIRTUAL_INDEX`, `nodePda(index)` | removed — signer accounts are `registry.nodes[bit]`; `nodePda(owner)` |
824
-
825
855
  ## Develop
826
856
 
827
857
  ```bash
@@ -902,12 +932,6 @@ Versions follow semver and are driven by the nature of each change, not by the b
902
932
 
903
933
  The `dev` workflow should guard against this and fail until a stable `latest` exists.
904
934
 
905
- 3. Deprecate the legacy package name on npm (one-time, after `@molpha/sdk@0.1.0` is published):
906
-
907
- ```bash
908
- npm deprecate "@molpha-oracle/sdk" "Package renamed to @molpha/sdk. Please migrate."
909
- ```
910
-
911
935
  If `latest` ever points to a prerelease, repoint it after publishing a stable version:
912
936
 
913
937
  ```bash
@@ -1,6 +1,5 @@
1
1
  import { web3 } from '@anchor-lang/core';
2
2
  import { address, getAddressEncoder, getAddressDecoder } from '@solana/kit';
3
- import { ed25519 } from '@noble/curves/ed25519.js';
4
3
 
5
4
  // src/solana/kit.ts
6
5
  var TOKEN_PROGRAM_ADDRESS = address("TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA");
@@ -38,18 +37,7 @@ function setComputeUnitLimit(units) {
38
37
  function keypairFromSecretKey(secretKey) {
39
38
  return web3.Keypair.fromSecretKey(secretKey);
40
39
  }
41
- var isKeypair = (value) => typeof value === "object" && value !== null && "secretKey" in value && value.secretKey instanceof Uint8Array;
42
- function signerFromKeypair(keypair) {
43
- const seed = keypair.secretKey.slice(0, 32);
44
- return async (message) => ed25519.sign(message, seed);
45
- }
46
- function gatewaySignerFromWallet(wallet) {
47
- const molpha = wallet;
48
- if (molpha.signAuthMessage) return molpha.signAuthMessage;
49
- if ("payer" in wallet && isKeypair(wallet.payer)) return signerFromKeypair(wallet.payer);
50
- return void 0;
51
- }
52
40
 
53
- export { SYSTEM_PROGRAM_ADDRESS, TOKEN_PROGRAM_ADDRESS, addressBytes, addressFromBytes, findProgramAddressSync, gatewaySignerFromWallet, getAssociatedTokenAddressSync, keypairFromSecretKey, setComputeUnitLimit, signerFromKeypair, toPublicKey, toSolanaAddress };
54
- //# sourceMappingURL=chunk-DT6IKCWB.js.map
55
- //# sourceMappingURL=chunk-DT6IKCWB.js.map
41
+ export { SYSTEM_PROGRAM_ADDRESS, TOKEN_PROGRAM_ADDRESS, addressBytes, addressFromBytes, findProgramAddressSync, getAssociatedTokenAddressSync, keypairFromSecretKey, setComputeUnitLimit, toPublicKey, toSolanaAddress };
42
+ //# sourceMappingURL=chunk-2X22JY7Q.js.map
43
+ //# sourceMappingURL=chunk-2X22JY7Q.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/solana/kit.ts"],"names":[],"mappings":";;;;AAaO,IAAM,qBAAA,GAAwB,QAAQ,6CAA6C;AACnF,IAAM,gCAAA,GAAmC,OAAA;AAAA,EAC9C;AACF,CAAA;AACO,IAAM,sBAAA,GAAyB,QAAQ,kCAAkC;AAEhF,IAAM,iBAAiB,iBAAA,EAAkB;AACzC,IAAM,iBAAiB,iBAAA,EAAkB;AAElC,SAAS,gBAAgB,KAAA,EAA+B;AAC7D,EAAA,OAAO,QAAQ,OAAO,KAAA,KAAU,WAAW,KAAA,GAAQ,KAAA,CAAM,UAAU,CAAA;AACrE;AAEO,SAAS,YAAY,KAAA,EAA2D;AACrF,EAAA,OAAO,iBAAiB,IAAA,CAAK,SAAA,GAAY,QAAQ,IAAI,IAAA,CAAK,UAAU,KAAK,CAAA;AAC3E;AAEO,SAAS,aAAa,KAAA,EAAkC;AAC7D,EAAA,OAAO,WAAW,IAAA,CAAK,cAAA,CAAe,OAAO,eAAA,CAAgB,KAAK,CAAC,CAAC,CAAA;AACtE;AAGO,SAAS,iBAAiB,KAAA,EAA4B;AAC3D,EAAA,OAAO,cAAA,CAAe,OAAO,KAAK,CAAA;AACpC;AAEO,SAAS,sBAAA,CACd,OACA,cAAA,EACS;AACT,EAAA,MAAM,CAAC,GAAG,CAAA,GAAI,IAAA,CAAK,UAAU,sBAAA,CAAuB,KAAA,EAAO,WAAA,CAAY,cAAc,CAAC,CAAA;AACtF,EAAA,OAAO,gBAAgB,GAAG,CAAA;AAC5B;AAUO,SAAS,6BAAA,CACd,IAAA,EACA,KAAA,EACA,YAAA,GAA8B,qBAAA,EACrB;AACT,EAAA,OAAO,sBAAA;AAAA,IACL,CAAC,aAAa,KAAK,CAAA,EAAG,aAAa,YAAY,CAAA,EAAG,YAAA,CAAa,IAAI,CAAC,CAAA;AAAA,IACpE;AAAA,GACF;AACF;AAEO,SAAS,oBAAoB,KAAA,EAAkC;AACpE,EAAA,OAAO,IAAA,CAAK,oBAAA,CAAqB,mBAAA,CAAoB,EAAE,OAAO,CAAA;AAChE;AAEO,SAAS,qBAAqB,SAAA,EAAsC;AACzE,EAAA,OAAO,IAAA,CAAK,OAAA,CAAQ,aAAA,CAAc,SAAS,CAAA;AAC7C","file":"chunk-2X22JY7Q.js","sourcesContent":["import { web3 } from \"@anchor-lang/core\";\nimport { address, getAddressDecoder, getAddressEncoder, type Address } from \"@solana/kit\";\n\nexport type SolanaAddress = Address | string | InstanceType<typeof web3.PublicKey>;\nexport type SolanaConnection = InstanceType<typeof web3.Connection>;\nexport type SolanaKeypair = InstanceType<typeof web3.Keypair>;\nexport type SolanaInstruction = InstanceType<typeof web3.TransactionInstruction>;\nexport type SolanaAccountMeta = {\n pubkey: InstanceType<typeof web3.PublicKey>;\n isSigner: boolean;\n isWritable: boolean;\n};\n\nexport const TOKEN_PROGRAM_ADDRESS = address(\"TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA\");\nexport const ASSOCIATED_TOKEN_PROGRAM_ADDRESS = address(\n \"ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL\",\n);\nexport const SYSTEM_PROGRAM_ADDRESS = address(\"11111111111111111111111111111111\");\n\nconst addressEncoder = getAddressEncoder();\nconst addressDecoder = getAddressDecoder();\n\nexport function toSolanaAddress(value: SolanaAddress): Address {\n return address(typeof value === \"string\" ? value : value.toBase58());\n}\n\nexport function toPublicKey(value: SolanaAddress): InstanceType<typeof web3.PublicKey> {\n return value instanceof web3.PublicKey ? value : new web3.PublicKey(value);\n}\n\nexport function addressBytes(value: SolanaAddress): Uint8Array {\n return Uint8Array.from(addressEncoder.encode(toSolanaAddress(value)));\n}\n\n/** Base58 `Address` from 32 raw bytes (e.g. a `Registry.nodes[i]` entry). */\nexport function addressFromBytes(bytes: Uint8Array): Address {\n return addressDecoder.decode(bytes);\n}\n\nexport function findProgramAddressSync(\n seeds: Uint8Array[],\n programAddress: SolanaAddress,\n): Address {\n const [pda] = web3.PublicKey.findProgramAddressSync(seeds, toPublicKey(programAddress));\n return toSolanaAddress(pda);\n}\n\nexport function findProgramPublicKeySync(\n seeds: Uint8Array[],\n programAddress: SolanaAddress,\n): InstanceType<typeof web3.PublicKey> {\n const [pda] = web3.PublicKey.findProgramAddressSync(seeds, toPublicKey(programAddress));\n return pda;\n}\n\nexport function getAssociatedTokenAddressSync(\n mint: SolanaAddress,\n owner: SolanaAddress,\n tokenProgram: SolanaAddress = TOKEN_PROGRAM_ADDRESS,\n): Address {\n return findProgramAddressSync(\n [addressBytes(owner), addressBytes(tokenProgram), addressBytes(mint)],\n ASSOCIATED_TOKEN_PROGRAM_ADDRESS,\n );\n}\n\nexport function setComputeUnitLimit(units: number): SolanaInstruction {\n return web3.ComputeBudgetProgram.setComputeUnitLimit({ units });\n}\n\nexport function keypairFromSecretKey(secretKey: Uint8Array): SolanaKeypair {\n return web3.Keypair.fromSecretKey(secretKey);\n}\n\nexport function generateKeypair(): SolanaKeypair {\n return web3.Keypair.generate();\n}\n"]}