@molpha/sdk 0.2.0 → 0.3.0-dev-20261022065307
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 +72 -59
- package/dist/{chunk-H77BBZOL.js → chunk-KLHORIAC.js} +18 -7
- package/dist/chunk-KLHORIAC.js.map +1 -0
- package/dist/index.d.ts +453 -74
- package/dist/index.js +3781 -469
- package/dist/index.js.map +1 -1
- package/dist/utils.d.ts +1 -1
- package/dist/utils.js +1 -1
- package/dist/{wallet-DGe_pi93.d.ts → wallet-BAxBy7hR.d.ts} +11 -45
- package/idl/molpha.json +2 -2
- package/package.json +47 -29
- package/dist/chunk-H77BBZOL.js.map +0 -1
package/README.md
CHANGED
|
@@ -13,7 +13,7 @@ Links: [molpha.io](https://molpha.io) · [GitHub](https://github.com/Molpha/sdk)
|
|
|
13
13
|
Use it to:
|
|
14
14
|
|
|
15
15
|
- subscribe to a Molpha plan on Solana;
|
|
16
|
-
- derive a source id from
|
|
16
|
+
- derive a source id from a source definition;
|
|
17
17
|
- request a threshold-signed attestation from the gateway;
|
|
18
18
|
- submit the signed result on-chain (`submit_attestation`);
|
|
19
19
|
- verify/read the latest feed value;
|
|
@@ -30,7 +30,7 @@ At a high level:
|
|
|
30
30
|
```text
|
|
31
31
|
Consumer
|
|
32
32
|
└─ subscribes (USDC) on Solana
|
|
33
|
-
└─ derives sourceId = keccak256(canonical
|
|
33
|
+
└─ derives sourceId = keccak256(canonical source)
|
|
34
34
|
└─ signs a RequestAuth bound to (programId, gateway, sourceId, signaturesRequired, authTimestamp)
|
|
35
35
|
|
|
36
36
|
Gateway
|
|
@@ -100,7 +100,7 @@ The package is ESM with `"sideEffects": false`, so gateway-only or read-only app
|
|
|
100
100
|
|
|
101
101
|
```ts
|
|
102
102
|
import { web3 } from "@anchor-lang/core";
|
|
103
|
-
import { MolphaSDK, PlanType,
|
|
103
|
+
import { MolphaSDK, PlanType, jsonPriceSource } from "@molpha/sdk";
|
|
104
104
|
import { walletFromKeypairFile } from "@molpha/sdk/utils";
|
|
105
105
|
|
|
106
106
|
const wallet = walletFromKeypairFile("~/.config/solana/id.json");
|
|
@@ -116,19 +116,17 @@ await sdk.solana.subscribe(PlanType.Basic, {
|
|
|
116
116
|
maxPriceUsdc: plan.subscriptionPrice,
|
|
117
117
|
});
|
|
118
118
|
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
responseParser: "$.price",
|
|
122
|
-
};
|
|
119
|
+
// GET the URL, read the JSON number at $.price, sign it as an int256 with 6 decimals.
|
|
120
|
+
const source = jsonPriceSource({ url: "https://api.example.com/price", path: "$.price", decimals: 6 });
|
|
123
121
|
const signaturesRequired = 3;
|
|
124
122
|
|
|
125
123
|
const { result, signature, feed } = await sdk.requestAndSubmit({
|
|
126
|
-
|
|
124
|
+
source,
|
|
127
125
|
signaturesRequired,
|
|
128
126
|
});
|
|
129
127
|
|
|
130
128
|
// The round's identity, for reads and cross-chain verification.
|
|
131
|
-
const sourceId =
|
|
129
|
+
const sourceId = source.idHex; // === "0x" + result.payload.sourceId
|
|
132
130
|
```
|
|
133
131
|
|
|
134
132
|
`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.
|
|
@@ -251,7 +249,7 @@ Gateway auth is resolved automatically when you use `MolphaSDK`:
|
|
|
251
249
|
3. Else omit auth and use an all-zero `authSig`.
|
|
252
250
|
|
|
253
251
|
`MolphaSDK` passes the resolved signer to `sdk.gateway` as its default, so
|
|
254
|
-
`sdk.gateway.requestSignedData({
|
|
252
|
+
`sdk.gateway.requestSignedData({ source, signaturesRequired })` authenticates without an
|
|
255
253
|
explicit `signer`. Standalone `new MolphaGateway(...)` omits auth unless you pass
|
|
256
254
|
a `defaultSigner` (third constructor arg) or per-call `signer`.
|
|
257
255
|
|
|
@@ -290,7 +288,8 @@ import { web3 } from "@anchor-lang/core";
|
|
|
290
288
|
import {
|
|
291
289
|
MolphaSDK,
|
|
292
290
|
PlanType,
|
|
293
|
-
|
|
291
|
+
jsonPriceSource,
|
|
292
|
+
defineSource,
|
|
294
293
|
} from "@molpha/sdk";
|
|
295
294
|
import { walletFromKeypairFile } from "@molpha/sdk/utils";
|
|
296
295
|
|
|
@@ -317,40 +316,55 @@ const { pricePaid } = await sdk.solana.subscribe(PlanType.Basic, {
|
|
|
317
316
|
|
|
318
317
|
`maxPriceUsdc` is a safety bound. The transaction aborts if the live plan price is higher than the amount the user approved.
|
|
319
318
|
|
|
320
|
-
### 2. Source
|
|
319
|
+
### 2. Source
|
|
321
320
|
|
|
322
|
-
There is no create-feed instruction. A data source is identified by its canonical
|
|
321
|
+
There is no create-feed instruction. A data source is one JSON document, identified by its canonical bytes:
|
|
323
322
|
|
|
324
323
|
```text
|
|
325
|
-
sourceId = keccak256(
|
|
324
|
+
sourceId = keccak256(canonical source bytes)
|
|
326
325
|
```
|
|
327
326
|
|
|
328
327
|
```ts
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
328
|
+
// The common case: one JSON number from one URL.
|
|
329
|
+
const source = jsonPriceSource({ url: "https://api.example.com/price", path: "$.price", decimals: 6 });
|
|
330
|
+
source.idHex; // "0x" + 64 hex chars
|
|
331
|
+
```
|
|
332
|
+
|
|
333
|
+
`defineSource` builds anything else. A source has up to four typed **inputs** (an HTTP request, an EVM or Starknet call, storage slot or balance read at a pinned block, or a Solana account), a **transform** (a JSON expression over exact decimals), **assertions** that must hold before anyone signs, an **output** type that fixes how the result becomes the signed 32 bytes (`int256`, `uint256`, `bool`, `bytes32`, `string32`, `keccak256`), and an optional [tolerance policy](#median-tolerance-mode):
|
|
333
334
|
|
|
334
|
-
|
|
335
|
+
```ts
|
|
336
|
+
import { defineSource, sx } from "@molpha/sdk";
|
|
337
|
+
|
|
338
|
+
const source = defineSource({
|
|
339
|
+
inputs: {
|
|
340
|
+
rate: sx.evmCall({
|
|
341
|
+
chain: "eip155:1", to: "0x7f39c581f595b53c5cb19bd0b3f8da6c935e2ca0", sig: "stEthPerToken()",
|
|
342
|
+
finality: { mode: "finalized", lagMs: 900_000 }, // read a finalized block 15 minutes behind the round
|
|
343
|
+
decode: sx.abiDecode(["uint256"], { rate: "0" }),
|
|
344
|
+
}),
|
|
345
|
+
},
|
|
346
|
+
transform: sx.ref("rate.rate"),
|
|
347
|
+
output: { type: "uint256", decimals: 18 },
|
|
348
|
+
});
|
|
335
349
|
```
|
|
336
350
|
|
|
337
|
-
|
|
351
|
+
On the wire a source has every key present and every number a string; `defineSource` and the builders (`sx.*`) fill the defaults and convert JS numbers, and a document that breaks a rule throws a `SourceError` naming the path before any request is made. The schema, the operators and the limits are in the node client's `docs/source-format.md`.
|
|
338
352
|
|
|
339
|
-
The gateway, the
|
|
353
|
+
The canonical form is UTF-8 JSON with sorted keys, no whitespace, and numbers as strings (a strict subset of RFC 8785). The gateway, the nodes and this SDK all recompute `sourceId` from the same document, so pass the same `source` (including `{{secret.*}}` placeholders) every time; the Solana program and the EVM/Starknet verifiers treat it as an opaque `bytes32`. `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.
|
|
340
354
|
|
|
341
355
|
### 3. Request signed data from the gateway
|
|
342
356
|
|
|
343
357
|
```ts
|
|
344
358
|
const signaturesRequired = 3;
|
|
345
359
|
const result = await sdk.gateway.requestSignedData({
|
|
346
|
-
|
|
360
|
+
source,
|
|
347
361
|
signaturesRequired,
|
|
348
362
|
});
|
|
349
363
|
```
|
|
350
364
|
|
|
351
365
|
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.
|
|
352
366
|
|
|
353
|
-
The returned `Attestation` matches the cross-VM struct (`payload` + `signature`), plus gateway-only `value` (
|
|
367
|
+
The returned `Attestation` matches the cross-VM struct (`payload` + `signature`), plus gateway-only `value` (the signed word rendered by the source's output type), `fresh` and, for a `keccak256` output, `valuePreimage`. `payload` carries `sourceId`, the signed 32-byte `value`, `timestamp`, `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.
|
|
354
368
|
|
|
355
369
|
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.
|
|
356
370
|
|
|
@@ -362,7 +376,7 @@ const { signature, feed } = await sdk.solana.submitAttestation(result);
|
|
|
362
376
|
|
|
363
377
|
`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.
|
|
364
378
|
|
|
365
|
-
|
|
379
|
+
A source with a `keccak256` output signs the digest of a longer byte string. The gateway returns those bytes as `result.valuePreimage`, and `submitAttestation` passes them as `rawValue` when they are at most 256 bytes, verifying the digest before sending (the program then stores the preimage's hash and marks the feed `Hash`). To pass a preimage yourself:
|
|
366
380
|
|
|
367
381
|
```ts
|
|
368
382
|
const { signature, feed } = await sdk.solana.submitAttestation(result, { rawValue });
|
|
@@ -386,7 +400,7 @@ The subscription read does not expose usage: the program stores no `used_rounds`
|
|
|
386
400
|
|
|
387
401
|
```ts
|
|
388
402
|
const { result, signature, feed } = await sdk.requestAndSubmit({
|
|
389
|
-
|
|
403
|
+
source,
|
|
390
404
|
signaturesRequired,
|
|
391
405
|
});
|
|
392
406
|
```
|
|
@@ -394,7 +408,7 @@ const { result, signature, feed } = await sdk.requestAndSubmit({
|
|
|
394
408
|
This is equivalent to:
|
|
395
409
|
|
|
396
410
|
```ts
|
|
397
|
-
const result = await sdk.gateway.requestSignedData({
|
|
411
|
+
const result = await sdk.gateway.requestSignedData({ source, signaturesRequired });
|
|
398
412
|
const { signature, feed } = await sdk.solana.submitAttestation(result);
|
|
399
413
|
```
|
|
400
414
|
|
|
@@ -460,7 +474,7 @@ round is a single gateway POST.
|
|
|
460
474
|
const context = await sdk.gateway.prepareContext();
|
|
461
475
|
|
|
462
476
|
// Reuse it across rounds — no prelude fetches.
|
|
463
|
-
const result = await sdk.gateway.requestSignedData({
|
|
477
|
+
const result = await sdk.gateway.requestSignedData({ source, signaturesRequired, context });
|
|
464
478
|
```
|
|
465
479
|
|
|
466
480
|
`context` is a `Partial<RoundContext>`, so you can cache only what you have
|
|
@@ -468,7 +482,7 @@ and let `requestSignedData` fetch the rest:
|
|
|
468
482
|
|
|
469
483
|
```ts
|
|
470
484
|
const result = await sdk.gateway.requestSignedData({
|
|
471
|
-
|
|
485
|
+
source,
|
|
472
486
|
signaturesRequired,
|
|
473
487
|
context: { nodes }, // registryVersion + redundancyBuffer + nodeCount still fetched fresh
|
|
474
488
|
});
|
|
@@ -482,37 +496,34 @@ disagrees with it. The same `context` field is accepted by `requestAndSubmit`.
|
|
|
482
496
|
|
|
483
497
|
## Median tolerance mode
|
|
484
498
|
|
|
485
|
-
By default every signing node must
|
|
486
|
-
(prices), add
|
|
499
|
+
By default every signing node must produce the identical 32 bytes. For noisy numeric sources
|
|
500
|
+
(prices), add a tolerance policy and the selected nodes instead exchange signed
|
|
487
501
|
observations, drop stale ones and outliers, and sign the **lower median** of
|
|
488
502
|
`signaturesRequired` surviving observations:
|
|
489
503
|
|
|
490
504
|
```ts
|
|
491
|
-
const
|
|
505
|
+
const source = jsonPriceSource({
|
|
492
506
|
url: "https://api.example.com/price",
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
maxAgeMs: 2000, // > 0: max observation age in milliseconds
|
|
499
|
-
numeric: { type: "int256", decimals: 8 }, // value = round-half-even(price * 10^8)
|
|
507
|
+
path: "$.price",
|
|
508
|
+
decimals: 8, // value = round-half-even(price * 10^8)
|
|
509
|
+
tolerance: {
|
|
510
|
+
maxDeviationBps: 50, // allowed distance from the lower median, in bps
|
|
511
|
+
maxAgeMs: 2000, // > 0: max observation age in milliseconds
|
|
500
512
|
},
|
|
501
|
-
};
|
|
513
|
+
});
|
|
502
514
|
|
|
503
|
-
const { result } = await sdk.requestAndSubmit({
|
|
515
|
+
const { result } = await sdk.requestAndSubmit({ source, signaturesRequired: 5 });
|
|
504
516
|
```
|
|
505
517
|
|
|
506
|
-
Rules (the node is the reference; the SDK rejects violations before any request is made, with `
|
|
518
|
+
With `defineSource` the policy is the `aggregation` field (`{ maxDeviationBps, maxAgeMs }`). Rules (the node is the reference; the SDK rejects violations before any request is made, with `SourceError`):
|
|
507
519
|
|
|
508
|
-
- `aggregation` is part of the `sourceId`
|
|
509
|
-
- Only `rule: "median"`
|
|
510
|
-
- Tolerance needs `signaturesRequired >= 3
|
|
511
|
-
- The
|
|
512
|
-
-
|
|
513
|
-
- 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.
|
|
520
|
+
- `aggregation` is part of the `sourceId`; `null` (or omitted) is exact mode.
|
|
521
|
+
- Only `rule: "median"` is supported, `maxAgeMs` must be positive, and the source's `output` must be `int256`: its `decimals` is the scale of the signed value, so there is no separate numeric block.
|
|
522
|
+
- Tolerance needs `signaturesRequired >= 3` (`assertToleranceQuorum`).
|
|
523
|
+
- 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 output's `decimals`, and `signature.signersBitmap` / signature fields must come from the response, since the nodes choose the final signing set after the observation exchange.
|
|
524
|
+
- Each node's observation is the final result of its transform, so the median is taken after any arithmetic, and a false assertion drops that node's observation.
|
|
514
525
|
|
|
515
|
-
Helpers for the signed value (mirror the node's `
|
|
526
|
+
Helpers for the signed value (mirror the node's `eval` package):
|
|
516
527
|
|
|
517
528
|
```ts
|
|
518
529
|
import {
|
|
@@ -530,14 +541,15 @@ const price = formatInt256Decimal(Uint8Array.from(feedState!.value), 8);
|
|
|
530
541
|
|
|
531
542
|
## Private APIs and encrypted secrets
|
|
532
543
|
|
|
533
|
-
Sources can use private APIs without sending plaintext secrets to the gateway.
|
|
544
|
+
Sources can use private APIs without sending plaintext secrets to the gateway. A `{{secret.NAME}}` placeholder may stand in an `http` input's URL (after the host and port, which stay literal), a header value or a request body text; anywhere else it is rejected.
|
|
534
545
|
|
|
535
546
|
```ts
|
|
536
547
|
const result = await sdk.gateway.requestSignedData({
|
|
537
|
-
|
|
548
|
+
source: jsonPriceSource({
|
|
538
549
|
url: "https://api.example.com/private-price?key={{secret.apiKey}}",
|
|
539
|
-
|
|
540
|
-
|
|
550
|
+
path: "$.price",
|
|
551
|
+
decimals: 6,
|
|
552
|
+
}),
|
|
541
553
|
signaturesRequired,
|
|
542
554
|
encrypt: {
|
|
543
555
|
secrets: {
|
|
@@ -549,7 +561,7 @@ const result = await sdk.gateway.requestSignedData({
|
|
|
549
561
|
|
|
550
562
|
`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.
|
|
551
563
|
|
|
552
|
-
Secrets are encrypted into per-node envelopes. The gateway coordinates the round but should not receive plaintext API credentials. Secrets are encrypted for every node of the registry (the committee is unknown until the gateway stamps the round), and the gateway forwards only the selected nodes' envelopes. `verifyNodeKeys` therefore authenticates all of them. The encrypted plaintext is the canonical
|
|
564
|
+
Secrets are encrypted into per-node envelopes. The gateway coordinates the round but should not receive plaintext API credentials. Secrets are encrypted for every node of the registry (the committee is unknown until the gateway stamps the round), and the gateway forwards only the selected nodes' envelopes. `verifyNodeKeys` therefore authenticates all of them. The encrypted plaintext is the canonical source with secrets substituted; a node accepts it only if it equals the public source everywhere except at the placeholders, so a secret can authenticate a read but cannot change what is read.
|
|
553
565
|
|
|
554
566
|
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.
|
|
555
567
|
|
|
@@ -564,7 +576,7 @@ source still costs exactly one round of subscription quota.
|
|
|
564
576
|
import { createEvmSignerFromPrivateKey } from "@molpha/sdk";
|
|
565
577
|
|
|
566
578
|
const result = await sdk.gateway.requestSignedData({
|
|
567
|
-
|
|
579
|
+
source,
|
|
568
580
|
signaturesRequired,
|
|
569
581
|
sourcePayment: {
|
|
570
582
|
signer: createEvmSignerFromPrivateKey(process.env.EVM_PRIVATE_KEY!),
|
|
@@ -591,8 +603,9 @@ settled stay spent if the round then fails; unsettled ones expire worthless. The
|
|
|
591
603
|
refund path and none is needed.
|
|
592
604
|
|
|
593
605
|
Source payment is per-round access material, like a credential. It never enters
|
|
594
|
-
`sourceId`, so a paid and an unpaid fetch of the same
|
|
595
|
-
identity.
|
|
606
|
+
`sourceId`, so a paid and an unpaid fetch of the same source share one source
|
|
607
|
+
identity. A paid source has exactly one `http` input: the authorization names no host, so the
|
|
608
|
+
nodes attach it to that input.
|
|
596
609
|
|
|
597
610
|
### Without a source wallet
|
|
598
611
|
|
|
@@ -604,7 +617,7 @@ detail. This is terminal — the round is never retried blindly.
|
|
|
604
617
|
import { UpstreamPaymentRequiredError } from "@molpha/sdk";
|
|
605
618
|
|
|
606
619
|
try {
|
|
607
|
-
await sdk.gateway.requestSignedData({
|
|
620
|
+
await sdk.gateway.requestSignedData({ source, signaturesRequired });
|
|
608
621
|
} catch (err) {
|
|
609
622
|
if (err instanceof UpstreamPaymentRequiredError) {
|
|
610
623
|
console.log(`${err.quote.resource} needs ${err.quote.eligibleSetSize} paid fetches`);
|
|
@@ -644,7 +657,7 @@ The verifier's entrypoint is
|
|
|
644
657
|
```ts
|
|
645
658
|
import { buildEvmVerifierArgs } from "@molpha/sdk";
|
|
646
659
|
|
|
647
|
-
const result = await sdk.gateway.requestSignedData({
|
|
660
|
+
const result = await sdk.gateway.requestSignedData({ source, signaturesRequired });
|
|
648
661
|
|
|
649
662
|
const { attestation, maxAge } = buildEvmVerifierArgs(result, { maxAge: 300 });
|
|
650
663
|
```
|
|
@@ -797,7 +810,7 @@ The verifier's entrypoint is `verify(attestation: Attestation, max_age: u64) ->
|
|
|
797
810
|
```ts
|
|
798
811
|
import { buildStarknetVerifierArgs } from "@molpha/sdk";
|
|
799
812
|
|
|
800
|
-
const result = await sdk.gateway.requestSignedData({
|
|
813
|
+
const result = await sdk.gateway.requestSignedData({ source, signaturesRequired });
|
|
801
814
|
|
|
802
815
|
const { attestation, maxAge } = buildStarknetVerifierArgs(result, { maxAge: 300 });
|
|
803
816
|
```
|
|
@@ -1,12 +1,20 @@
|
|
|
1
1
|
import { web3 } from '@anchor-lang/core';
|
|
2
2
|
import { address, getAddressEncoder, getAddressDecoder } from '@solana/kit';
|
|
3
3
|
|
|
4
|
-
|
|
5
|
-
var
|
|
4
|
+
var __defProp = Object.defineProperty;
|
|
5
|
+
var __export = (target, all) => {
|
|
6
|
+
for (var name in all)
|
|
7
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
8
|
+
};
|
|
9
|
+
var TOKEN_PROGRAM_ADDRESS = address(
|
|
10
|
+
"TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA"
|
|
11
|
+
);
|
|
6
12
|
var ASSOCIATED_TOKEN_PROGRAM_ADDRESS = address(
|
|
7
13
|
"ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL"
|
|
8
14
|
);
|
|
9
|
-
var SYSTEM_PROGRAM_ADDRESS = address(
|
|
15
|
+
var SYSTEM_PROGRAM_ADDRESS = address(
|
|
16
|
+
"11111111111111111111111111111111"
|
|
17
|
+
);
|
|
10
18
|
var addressEncoder = getAddressEncoder();
|
|
11
19
|
var addressDecoder = getAddressDecoder();
|
|
12
20
|
function toSolanaAddress(value) {
|
|
@@ -22,7 +30,10 @@ function addressFromBytes(bytes) {
|
|
|
22
30
|
return addressDecoder.decode(bytes);
|
|
23
31
|
}
|
|
24
32
|
function findProgramAddressSync(seeds, programAddress) {
|
|
25
|
-
const [pda] = web3.PublicKey.findProgramAddressSync(
|
|
33
|
+
const [pda] = web3.PublicKey.findProgramAddressSync(
|
|
34
|
+
seeds,
|
|
35
|
+
toPublicKey(programAddress)
|
|
36
|
+
);
|
|
26
37
|
return toSolanaAddress(pda);
|
|
27
38
|
}
|
|
28
39
|
function getAssociatedTokenAddressSync(mint, owner, tokenProgram = TOKEN_PROGRAM_ADDRESS) {
|
|
@@ -41,6 +52,6 @@ function keypairFromSecretKey(secretKey) {
|
|
|
41
52
|
return web3.Keypair.fromSecretKey(secretKey);
|
|
42
53
|
}
|
|
43
54
|
|
|
44
|
-
export { SYSTEM_PROGRAM_ADDRESS, TOKEN_PROGRAM_ADDRESS, addressBytes, addressFromBytes, findProgramAddressSync, getAssociatedTokenAddressSync, keypairFromSecretKey, setComputeUnitLimit, setComputeUnitPrice, toPublicKey, toSolanaAddress };
|
|
45
|
-
//# sourceMappingURL=chunk-
|
|
46
|
-
//# sourceMappingURL=chunk-
|
|
55
|
+
export { SYSTEM_PROGRAM_ADDRESS, TOKEN_PROGRAM_ADDRESS, __export, addressBytes, addressFromBytes, findProgramAddressSync, getAssociatedTokenAddressSync, keypairFromSecretKey, setComputeUnitLimit, setComputeUnitPrice, toPublicKey, toSolanaAddress };
|
|
56
|
+
//# sourceMappingURL=chunk-KLHORIAC.js.map
|
|
57
|
+
//# sourceMappingURL=chunk-KLHORIAC.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/solana/kit.ts"],"names":[],"mappings":";;;;;;;;AAqBO,IAAM,qBAAA,GAAwB,OAAA;AAAA,EACnC;AACF;AACO,IAAM,gCAAA,GAAmC,OAAA;AAAA,EAC9C;AACF,CAAA;AACO,IAAM,sBAAA,GAAyB,OAAA;AAAA,EACpC;AACF;AAEA,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,YACd,KAAA,EACqC;AACrC,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,SAAA,CAAU,sBAAA;AAAA,IAC3B,KAAA;AAAA,IACA,YAAY,cAAc;AAAA,GAC5B;AACA,EAAA,OAAO,gBAAgB,GAAG,CAAA;AAC5B;AAaO,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,oBAAoB,aAAA,EAA0C;AAC5E,EAAA,OAAO,IAAA,CAAK,oBAAA,CAAqB,mBAAA,CAAoB,EAAE,eAAe,CAAA;AACxE;AAEO,SAAS,qBAAqB,SAAA,EAAsC;AACzE,EAAA,OAAO,IAAA,CAAK,OAAA,CAAQ,aAAA,CAAc,SAAS,CAAA;AAC7C","file":"chunk-KLHORIAC.js","sourcesContent":["import { web3 } from \"@anchor-lang/core\";\nimport {\n address,\n getAddressDecoder,\n getAddressEncoder,\n type Address,\n} from \"@solana/kit\";\n\nexport type SolanaAddress =\n Address | string | InstanceType<typeof web3.PublicKey>;\nexport type SolanaConnection = InstanceType<typeof web3.Connection>;\nexport type SolanaKeypair = InstanceType<typeof web3.Keypair>;\nexport type SolanaInstruction = InstanceType<\n typeof web3.TransactionInstruction\n>;\nexport type SolanaAccountMeta = {\n pubkey: InstanceType<typeof web3.PublicKey>;\n isSigner: boolean;\n isWritable: boolean;\n};\n\nexport const TOKEN_PROGRAM_ADDRESS = address(\n \"TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA\",\n);\nexport const ASSOCIATED_TOKEN_PROGRAM_ADDRESS = address(\n \"ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL\",\n);\nexport const SYSTEM_PROGRAM_ADDRESS = address(\n \"11111111111111111111111111111111\",\n);\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(\n value: SolanaAddress,\n): 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(\n seeds,\n toPublicKey(programAddress),\n );\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(\n seeds,\n toPublicKey(programAddress),\n );\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 setComputeUnitPrice(microLamports: number): SolanaInstruction {\n return web3.ComputeBudgetProgram.setComputeUnitPrice({ microLamports });\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"]}
|