@opaquecash/stealth-chain-solana 0.2.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.
- package/README.md +69 -0
- package/dist/adapter.d.ts +76 -0
- package/dist/adapter.d.ts.map +1 -0
- package/dist/adapter.js +114 -0
- package/dist/adapter.js.map +1 -0
- package/dist/announcer.d.ts +92 -0
- package/dist/announcer.d.ts.map +1 -0
- package/dist/announcer.js +164 -0
- package/dist/announcer.js.map +1 -0
- package/dist/bytes.d.ts +35 -0
- package/dist/bytes.d.ts.map +1 -0
- package/dist/bytes.js +78 -0
- package/dist/bytes.js.map +1 -0
- package/dist/index.d.ts +24 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +24 -0
- package/dist/index.js.map +1 -0
- package/dist/ons.d.ts +122 -0
- package/dist/ons.d.ts.map +1 -0
- package/dist/ons.js +167 -0
- package/dist/ons.js.map +1 -0
- package/dist/programs.d.ts +60 -0
- package/dist/programs.d.ts.map +1 -0
- package/dist/programs.js +69 -0
- package/dist/programs.js.map +1 -0
- package/dist/registry.d.ts +39 -0
- package/dist/registry.d.ts.map +1 -0
- package/dist/registry.js +69 -0
- package/dist/registry.js.map +1 -0
- package/dist/relay.d.ts +71 -0
- package/dist/relay.d.ts.map +1 -0
- package/dist/relay.js +102 -0
- package/dist/relay.js.map +1 -0
- package/dist/sns.d.ts +16 -0
- package/dist/sns.d.ts.map +1 -0
- package/dist/sns.js +38 -0
- package/dist/sns.js.map +1 -0
- package/dist/stealth.d.ts +22 -0
- package/dist/stealth.d.ts.map +1 -0
- package/dist/stealth.js +38 -0
- package/dist/stealth.js.map +1 -0
- package/dist/sweep.d.ts +41 -0
- package/dist/sweep.d.ts.map +1 -0
- package/dist/sweep.js +76 -0
- package/dist/sweep.js.map +1 -0
- package/dist/uab-receiver.d.ts +57 -0
- package/dist/uab-receiver.d.ts.map +1 -0
- package/dist/uab-receiver.js +121 -0
- package/dist/uab-receiver.js.map +1 -0
- package/idl/stealth_announcer.json +460 -0
- package/package.json +42 -0
package/README.md
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
# @opaquecash/stealth-chain-solana
|
|
2
|
+
|
|
3
|
+
Solana (`@solana/web3.js`) integration for the Opaque stealth registry and announcer — the
|
|
4
|
+
Solana counterpart to `@opaquecash/stealth-chain` (EVM/viem).
|
|
5
|
+
|
|
6
|
+
All DKSAP crypto is shared with the Ethereum path via the chain-neutral core
|
|
7
|
+
(`@opaquecash/stealth-core` / `opaque-scanner` WASM). Only chain access lives here: program
|
|
8
|
+
ids, PDA derivation, Anchor instruction building, and `Announcement` log decoding.
|
|
9
|
+
|
|
10
|
+
## What's here
|
|
11
|
+
|
|
12
|
+
- **`SolanaAdapter`** — implements `@opaquecash/adapter`'s `ChainAdapter`
|
|
13
|
+
(`fetchAnnouncements`, `resolveMetaAddress`, `isRegistered`, `watchAnnouncements`) and adds
|
|
14
|
+
`buildAnnounceInstruction` / `buildRegisterKeysInstruction`.
|
|
15
|
+
- **Registry** — `getRegistryEntryPda` (`["stealth_meta", registrant, schemeId_le]`),
|
|
16
|
+
`buildRegisterKeysInstruction`, `resolveMetaAddress`, `isRegistered`,
|
|
17
|
+
`decodeRegistryEntryMetaAddress`.
|
|
18
|
+
- **Announcer** — `buildAnnounceInstruction`, `decodeAnnouncementLogs` /
|
|
19
|
+
`decodeAnnouncementEventData` / `encodeAnnouncementEventData`, `fetchAnnouncementsRange`,
|
|
20
|
+
`watchAnnouncements`.
|
|
21
|
+
- **Stealth destinations** — `deriveStealthSolanaKeypair[FromStealthPrivKey]` and the
|
|
22
|
+
matching address helpers (`Keypair.fromSeed(sha256("opaque-solana-stealth-v1" || pubkey))`).
|
|
23
|
+
- **Config** — `getSolanaDeployment(cluster)`, `SOLANA_DEPLOYMENTS`, `CLUSTER_ENDPOINTS`,
|
|
24
|
+
discriminators, `SCHEME_ID_SECP256K1`.
|
|
25
|
+
|
|
26
|
+
This package never reads `import.meta.env` or any ambient config: pass a `Connection`,
|
|
27
|
+
`rpcUrl`, or `cluster` explicitly. Signing stays in the app's wallet layer — the builders
|
|
28
|
+
return unsigned `TransactionInstruction`s.
|
|
29
|
+
|
|
30
|
+
## Usage
|
|
31
|
+
|
|
32
|
+
```ts
|
|
33
|
+
import { Connection, PublicKey } from "@solana/web3.js";
|
|
34
|
+
import { SolanaAdapter } from "@opaquecash/stealth-chain-solana";
|
|
35
|
+
|
|
36
|
+
const adapter = new SolanaAdapter({ cluster: "devnet" });
|
|
37
|
+
|
|
38
|
+
// Unified inbox (chain-neutral announcements; run the WASM view-tag/DKSAP filter next).
|
|
39
|
+
const announcements = await adapter.fetchAnnouncements({ limit: 500 });
|
|
40
|
+
|
|
41
|
+
// Resolve a recipient's meta-address by Solana pubkey.
|
|
42
|
+
const meta = await adapter.resolveMetaAddress("E9LBRG5e...");
|
|
43
|
+
|
|
44
|
+
// Build an announce instruction for the wallet layer to sign.
|
|
45
|
+
const ix = adapter.buildAnnounceInstruction({
|
|
46
|
+
caller: new PublicKey("..."),
|
|
47
|
+
stealthAddress, // 20-byte EVM-style bytes from computeStealthAddressAndViewTag
|
|
48
|
+
ephemeralPubKey, // 33-byte compressed secp256k1
|
|
49
|
+
metadata, // metadata[0] = view tag
|
|
50
|
+
});
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## IDL
|
|
54
|
+
|
|
55
|
+
`idl/stealth_announcer.json` is the deployed program IDL (devnet
|
|
56
|
+
`HGFn2fH7bVQ5cSuiG52NjzN9m11YrB3FZUfoN9b9A5jf`), vendored for consumers that prefer Anchor.
|
|
57
|
+
This package decodes/encodes with hardcoded discriminators (sourced from that IDL) so it has
|
|
58
|
+
no Anchor runtime dependency.
|
|
59
|
+
|
|
60
|
+
## Devnet program ids
|
|
61
|
+
|
|
62
|
+
| Program | Id |
|
|
63
|
+
| --- | --- |
|
|
64
|
+
| Stealth registry | `E9LBRG5eP2kvuNfveouqQ9tA5P6nrpyLyWFjH9MFYVno` |
|
|
65
|
+
| Stealth announcer | `HGFn2fH7bVQ5cSuiG52NjzN9m11YrB3FZUfoN9b9A5jf` |
|
|
66
|
+
| Schema registry | `FbgMJYGWnLKLcrKYS1NxM5uER1ihQkYLMTLs4STuDMWB` |
|
|
67
|
+
| Attestation engine V2 | `4T9kPCVCFGdEuLpEqRJihsPCbEEo2LWWDEPFvUESEqtM` |
|
|
68
|
+
| Groth16 verifier | `6mFaKyp7F4NqNeoiBLEWSqy5wJSk7rWf1EYumVXgHvhQ` |
|
|
69
|
+
| Reputation verifier | `BSnkCDoTpgNVN5BbF3aN5L5EJPiaYUkqqj9MHp8kaqWM` |
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* {@link SolanaAdapter} — the Solana implementation of `@opaquecash/adapter`'s
|
|
3
|
+
* {@link ChainAdapter}. Wraps a `Connection` plus a {@link SolanaDeployment} (program ids)
|
|
4
|
+
* and exposes the chain-neutral read/scan surface the universal scanner consumes, alongside
|
|
5
|
+
* Solana-specific instruction builders for the app's wallet layer to sign.
|
|
6
|
+
*/
|
|
7
|
+
import { Connection, Keypair, PublicKey, TransactionInstruction, type Finality } from "@solana/web3.js";
|
|
8
|
+
import { type ChainAdapter, type Announcement, type AnnouncementHandlers, type FetchAnnouncementsOptions, type Hex } from "@opaquecash/adapter";
|
|
9
|
+
import { type SolanaCluster, type SolanaDeployment } from "./programs.js";
|
|
10
|
+
import { type AnnounceWithRelayBuild } from "./relay.js";
|
|
11
|
+
/** Construction options for {@link SolanaAdapter}. */
|
|
12
|
+
export interface SolanaAdapterConfig {
|
|
13
|
+
/** Pre-built connection (takes precedence over `rpcUrl`/`cluster`). */
|
|
14
|
+
connection?: Connection;
|
|
15
|
+
/** RPC URL to build a connection from (falls back to the cluster's public endpoint). */
|
|
16
|
+
rpcUrl?: string;
|
|
17
|
+
/** Target cluster (default `devnet`); selects bundled program ids and the public RPC. */
|
|
18
|
+
cluster?: SolanaCluster;
|
|
19
|
+
/** Program-id overrides (default: bundled deployment for `cluster`). */
|
|
20
|
+
deployment?: SolanaDeployment;
|
|
21
|
+
/** Read commitment for fetch/watch (default `confirmed`). */
|
|
22
|
+
commitment?: Finality;
|
|
23
|
+
}
|
|
24
|
+
export declare class SolanaAdapter implements ChainAdapter {
|
|
25
|
+
readonly chainId = 1;
|
|
26
|
+
readonly name = "solana";
|
|
27
|
+
readonly connection: Connection;
|
|
28
|
+
readonly deployment: SolanaDeployment;
|
|
29
|
+
private readonly commitment;
|
|
30
|
+
constructor(config?: SolanaAdapterConfig);
|
|
31
|
+
fetchAnnouncements(opts?: FetchAnnouncementsOptions): Promise<Announcement[]>;
|
|
32
|
+
resolveMetaAddress(identity: string): Promise<Hex | null>;
|
|
33
|
+
isRegistered(identity: string): Promise<boolean>;
|
|
34
|
+
watchAnnouncements(handlers: AnnouncementHandlers): () => void;
|
|
35
|
+
/** Build a `register_keys` instruction for `registrant`'s 66-byte meta-address. */
|
|
36
|
+
buildRegisterKeysInstruction(registrant: PublicKey, stealthMetaAddress: Uint8Array, schemeId?: bigint): TransactionInstruction;
|
|
37
|
+
/** Build an `announce` instruction (the `caller` signs and pays). */
|
|
38
|
+
buildAnnounceInstruction(params: {
|
|
39
|
+
caller: PublicKey;
|
|
40
|
+
stealthAddress: Uint8Array;
|
|
41
|
+
ephemeralPubKey: Uint8Array;
|
|
42
|
+
metadata: Uint8Array;
|
|
43
|
+
schemeId?: bigint;
|
|
44
|
+
}): TransactionInstruction;
|
|
45
|
+
/**
|
|
46
|
+
* Build a cross-chain `announce_with_relay` instruction (emits locally AND relays over Wormhole)
|
|
47
|
+
* plus the fresh message keypair that must co-sign the transaction. Resolves the announcer and
|
|
48
|
+
* Wormhole core program ids from this adapter's deployment.
|
|
49
|
+
*/
|
|
50
|
+
buildAnnounceWithRelay(params: {
|
|
51
|
+
caller: PublicKey;
|
|
52
|
+
stealthAddress: Uint8Array;
|
|
53
|
+
ephemeralPubKey: Uint8Array;
|
|
54
|
+
metadata: Uint8Array;
|
|
55
|
+
schemeId?: bigint;
|
|
56
|
+
batchId?: number;
|
|
57
|
+
wormholeFee?: bigint;
|
|
58
|
+
}): AnnounceWithRelayBuild;
|
|
59
|
+
/** Current Wormhole message fee (lamports) for `announce_with_relay`; `0n` on devnet. */
|
|
60
|
+
fetchWormholeMessageFee(): Promise<bigint>;
|
|
61
|
+
/**
|
|
62
|
+
* Sweep the full SOL balance of a one-time stealth account to `destination`. The stealth
|
|
63
|
+
* keypair signs and pays its own fee; pass the reconstructed 32-byte secp256k1 stealth
|
|
64
|
+
* private key (or the derived keypair).
|
|
65
|
+
*/
|
|
66
|
+
sweepStealthSol(params: {
|
|
67
|
+
stealthPrivKey?: Uint8Array;
|
|
68
|
+
stealthKeypair?: Keypair;
|
|
69
|
+
destination: PublicKey | string;
|
|
70
|
+
}): Promise<{
|
|
71
|
+
signature: string;
|
|
72
|
+
sweepLamports: bigint;
|
|
73
|
+
feeLamports: bigint;
|
|
74
|
+
}>;
|
|
75
|
+
}
|
|
76
|
+
//# sourceMappingURL=adapter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"adapter.d.ts","sourceRoot":"","sources":["../src/adapter.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EACL,UAAU,EACV,OAAO,EACP,SAAS,EACT,sBAAsB,EACtB,KAAK,QAAQ,EACd,MAAM,iBAAiB,CAAC;AACzB,OAAO,EACL,KAAK,YAAY,EACjB,KAAK,YAAY,EACjB,KAAK,oBAAoB,EACzB,KAAK,yBAAyB,EAC9B,KAAK,GAAG,EAET,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAGL,KAAK,aAAa,EAClB,KAAK,gBAAgB,EACtB,MAAM,eAAe,CAAC;AAOvB,OAAO,EACL,KAAK,sBAAsB,EAG5B,MAAM,YAAY,CAAC;AAQpB,sDAAsD;AACtD,MAAM,WAAW,mBAAmB;IAClC,uEAAuE;IACvE,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB,wFAAwF;IACxF,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,yFAAyF;IACzF,OAAO,CAAC,EAAE,aAAa,CAAC;IACxB,wEAAwE;IACxE,UAAU,CAAC,EAAE,gBAAgB,CAAC;IAC9B,6DAA6D;IAC7D,UAAU,CAAC,EAAE,QAAQ,CAAC;CACvB;AAED,qBAAa,aAAc,YAAW,YAAY;IAChD,QAAQ,CAAC,OAAO,KAAyB;IACzC,QAAQ,CAAC,IAAI,YAAY;IAEzB,QAAQ,CAAC,UAAU,EAAE,UAAU,CAAC;IAChC,QAAQ,CAAC,UAAU,EAAE,gBAAgB,CAAC;IACtC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAW;gBAE1B,MAAM,GAAE,mBAAwB;IAStC,kBAAkB,CACtB,IAAI,GAAE,yBAA8B,GACnC,OAAO,CAAC,YAAY,EAAE,CAAC;IAkBpB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,GAAG,IAAI,CAAC;IAOzD,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAOtD,kBAAkB,CAAC,QAAQ,EAAE,oBAAoB,GAAG,MAAM,IAAI;IAa9D,mFAAmF;IACnF,4BAA4B,CAC1B,UAAU,EAAE,SAAS,EACrB,kBAAkB,EAAE,UAAU,EAC9B,QAAQ,CAAC,EAAE,MAAM,GAChB,sBAAsB;IASzB,qEAAqE;IACrE,wBAAwB,CAAC,MAAM,EAAE;QAC/B,MAAM,EAAE,SAAS,CAAC;QAClB,cAAc,EAAE,UAAU,CAAC;QAC3B,eAAe,EAAE,UAAU,CAAC;QAC5B,QAAQ,EAAE,UAAU,CAAC;QACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;KACnB,GAAG,sBAAsB;IAO1B;;;;OAIG;IACH,sBAAsB,CAAC,MAAM,EAAE;QAC7B,MAAM,EAAE,SAAS,CAAC;QAClB,cAAc,EAAE,UAAU,CAAC;QAC3B,eAAe,EAAE,UAAU,CAAC;QAC5B,QAAQ,EAAE,UAAU,CAAC;QACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,WAAW,CAAC,EAAE,MAAM,CAAC;KACtB,GAAG,sBAAsB;IAQ1B,yFAAyF;IACnF,uBAAuB,IAAI,OAAO,CAAC,MAAM,CAAC;IAIhD;;;;OAIG;IACG,eAAe,CAAC,MAAM,EAAE;QAC5B,cAAc,CAAC,EAAE,UAAU,CAAC;QAC5B,cAAc,CAAC,EAAE,OAAO,CAAC;QACzB,WAAW,EAAE,SAAS,GAAG,MAAM,CAAC;KACjC,GAAG,OAAO,CAAC;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,aAAa,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAA;KAAE,CAAC;CAM/E"}
|
package/dist/adapter.js
ADDED
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* {@link SolanaAdapter} — the Solana implementation of `@opaquecash/adapter`'s
|
|
3
|
+
* {@link ChainAdapter}. Wraps a `Connection` plus a {@link SolanaDeployment} (program ids)
|
|
4
|
+
* and exposes the chain-neutral read/scan surface the universal scanner consumes, alongside
|
|
5
|
+
* Solana-specific instruction builders for the app's wallet layer to sign.
|
|
6
|
+
*/
|
|
7
|
+
import { Connection, } from "@solana/web3.js";
|
|
8
|
+
import { WORMHOLE_CHAIN_SOLANA, } from "@opaquecash/adapter";
|
|
9
|
+
import { CLUSTER_ENDPOINTS, getSolanaDeployment, } from "./programs.js";
|
|
10
|
+
import { buildAnnounceInstruction, fetchAnnouncementsRange, watchAnnouncements, } from "./announcer.js";
|
|
11
|
+
import { fetchCrossChainAnnouncementsRange } from "./uab-receiver.js";
|
|
12
|
+
import { buildAnnounceWithRelay, fetchWormholeMessageFee, } from "./relay.js";
|
|
13
|
+
import { sweepStealthSol } from "./sweep.js";
|
|
14
|
+
import { buildRegisterKeysInstruction, isRegistered, resolveMetaAddress, } from "./registry.js";
|
|
15
|
+
export class SolanaAdapter {
|
|
16
|
+
chainId = WORMHOLE_CHAIN_SOLANA;
|
|
17
|
+
name = "solana";
|
|
18
|
+
connection;
|
|
19
|
+
deployment;
|
|
20
|
+
commitment;
|
|
21
|
+
constructor(config = {}) {
|
|
22
|
+
const cluster = config.cluster ?? config.deployment?.cluster ?? "devnet";
|
|
23
|
+
this.deployment = config.deployment ?? getSolanaDeployment(cluster);
|
|
24
|
+
this.commitment = config.commitment ?? "confirmed";
|
|
25
|
+
this.connection =
|
|
26
|
+
config.connection ??
|
|
27
|
+
new Connection(config.rpcUrl ?? CLUSTER_ENDPOINTS[cluster], this.commitment);
|
|
28
|
+
}
|
|
29
|
+
async fetchAnnouncements(opts = {}) {
|
|
30
|
+
const native = await fetchAnnouncementsRange(this.connection, {
|
|
31
|
+
announcerProgramId: this.deployment.stealthAnnouncer,
|
|
32
|
+
limit: opts.limit,
|
|
33
|
+
commitment: this.commitment,
|
|
34
|
+
});
|
|
35
|
+
// Merge Ethereum-originated announcements mirrored by the uab-receiver program,
|
|
36
|
+
// normalised to the same shape (their chainId stays the origin chain's).
|
|
37
|
+
const includeCrossChain = opts.includeCrossChain ?? Boolean(this.deployment.uabReceiver);
|
|
38
|
+
if (!includeCrossChain)
|
|
39
|
+
return native;
|
|
40
|
+
const cross = await fetchCrossChainAnnouncementsRange(this.connection, {
|
|
41
|
+
uabReceiverProgramId: this.deployment.uabReceiver,
|
|
42
|
+
limit: opts.limit,
|
|
43
|
+
commitment: this.commitment,
|
|
44
|
+
});
|
|
45
|
+
return [...native, ...cross];
|
|
46
|
+
}
|
|
47
|
+
async resolveMetaAddress(identity) {
|
|
48
|
+
return resolveMetaAddress(this.connection, {
|
|
49
|
+
registryProgramId: this.deployment.stealthRegistry,
|
|
50
|
+
registrant: identity,
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
async isRegistered(identity) {
|
|
54
|
+
return isRegistered(this.connection, {
|
|
55
|
+
registryProgramId: this.deployment.stealthRegistry,
|
|
56
|
+
registrant: identity,
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
watchAnnouncements(handlers) {
|
|
60
|
+
return watchAnnouncements(this.connection, {
|
|
61
|
+
announcerProgramId: this.deployment.stealthAnnouncer,
|
|
62
|
+
commitment: this.commitment,
|
|
63
|
+
onAnnouncement: handlers.onAnnouncement,
|
|
64
|
+
onError: handlers.onError,
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
// ---------------------------------------------------------------------------
|
|
68
|
+
// Solana-specific instruction builders (app's wallet layer signs + submits).
|
|
69
|
+
// ---------------------------------------------------------------------------
|
|
70
|
+
/** Build a `register_keys` instruction for `registrant`'s 66-byte meta-address. */
|
|
71
|
+
buildRegisterKeysInstruction(registrant, stealthMetaAddress, schemeId) {
|
|
72
|
+
return buildRegisterKeysInstruction({
|
|
73
|
+
registryProgramId: this.deployment.stealthRegistry,
|
|
74
|
+
registrant,
|
|
75
|
+
stealthMetaAddress,
|
|
76
|
+
schemeId,
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
/** Build an `announce` instruction (the `caller` signs and pays). */
|
|
80
|
+
buildAnnounceInstruction(params) {
|
|
81
|
+
return buildAnnounceInstruction({
|
|
82
|
+
announcerProgramId: this.deployment.stealthAnnouncer,
|
|
83
|
+
...params,
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Build a cross-chain `announce_with_relay` instruction (emits locally AND relays over Wormhole)
|
|
88
|
+
* plus the fresh message keypair that must co-sign the transaction. Resolves the announcer and
|
|
89
|
+
* Wormhole core program ids from this adapter's deployment.
|
|
90
|
+
*/
|
|
91
|
+
buildAnnounceWithRelay(params) {
|
|
92
|
+
return buildAnnounceWithRelay({
|
|
93
|
+
announcerProgramId: this.deployment.stealthAnnouncer,
|
|
94
|
+
wormholeCore: this.deployment.wormholeCore,
|
|
95
|
+
...params,
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
/** Current Wormhole message fee (lamports) for `announce_with_relay`; `0n` on devnet. */
|
|
99
|
+
async fetchWormholeMessageFee() {
|
|
100
|
+
return fetchWormholeMessageFee(this.connection, this.deployment.wormholeCore);
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Sweep the full SOL balance of a one-time stealth account to `destination`. The stealth
|
|
104
|
+
* keypair signs and pays its own fee; pass the reconstructed 32-byte secp256k1 stealth
|
|
105
|
+
* private key (or the derived keypair).
|
|
106
|
+
*/
|
|
107
|
+
async sweepStealthSol(params) {
|
|
108
|
+
return sweepStealthSol(this.connection, {
|
|
109
|
+
...params,
|
|
110
|
+
commitment: this.commitment,
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
//# sourceMappingURL=adapter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"adapter.js","sourceRoot":"","sources":["../src/adapter.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `StealthAddressAnnouncer` (Solana) — `announce` instruction building, `Announcement`
|
|
3
|
+
* event decoding from transaction logs, historical range fetch, and live subscription.
|
|
4
|
+
*
|
|
5
|
+
* The on-chain `Announcement` event (Anchor `emit!`) is surfaced in transaction logs as a
|
|
6
|
+
* `Program data: <base64>` line: an 8-byte event discriminator followed by the Borsh body
|
|
7
|
+
* `{ scheme_id: u64, stealth_address: Vec<u8>, caller: Pubkey, ephemeral_pub_key: Vec<u8>,
|
|
8
|
+
* metadata: Vec<u8> }`. See `solana/target/idl/stealth_announcer.json`.
|
|
9
|
+
*/
|
|
10
|
+
import { Connection, PublicKey, TransactionInstruction, type Finality } from "@solana/web3.js";
|
|
11
|
+
import { type Announcement, type AnnouncementHandlers } from "@opaquecash/adapter";
|
|
12
|
+
/** Raw fields of a decoded on-chain `Announcement` event. */
|
|
13
|
+
export interface DecodedAnnouncementEvent {
|
|
14
|
+
schemeId: bigint;
|
|
15
|
+
/** Stealth address bytes as stored on-chain (20-byte EVM-style for scanner matching). */
|
|
16
|
+
stealthAddress: Uint8Array;
|
|
17
|
+
/** Announcer (caller) pubkey, 32 bytes. */
|
|
18
|
+
caller: Uint8Array;
|
|
19
|
+
/** Compressed secp256k1 ephemeral public key, 33 bytes. */
|
|
20
|
+
ephemeralPubKey: Uint8Array;
|
|
21
|
+
/** Announcement metadata (`metadata[0]` is the view tag). */
|
|
22
|
+
metadata: Uint8Array;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Build an `announce` instruction. `caller` signs and pays; the app's wallet layer submits.
|
|
26
|
+
*/
|
|
27
|
+
export declare function buildAnnounceInstruction(params: {
|
|
28
|
+
announcerProgramId: PublicKey;
|
|
29
|
+
caller: PublicKey;
|
|
30
|
+
/** Stealth address bytes (1..=32 bytes; Opaque uses the 20-byte EVM-style address). */
|
|
31
|
+
stealthAddress: Uint8Array;
|
|
32
|
+
/** 33-byte compressed secp256k1 ephemeral public key. */
|
|
33
|
+
ephemeralPubKey: Uint8Array;
|
|
34
|
+
/** Metadata; `metadata[0]` MUST be the view tag. */
|
|
35
|
+
metadata: Uint8Array;
|
|
36
|
+
schemeId?: bigint;
|
|
37
|
+
}): TransactionInstruction;
|
|
38
|
+
/**
|
|
39
|
+
* Encode the `Announcement` event body the way the program emits it (8-byte discriminator
|
|
40
|
+
* + Borsh). Useful for fixtures and round-trip tests.
|
|
41
|
+
*/
|
|
42
|
+
export declare function encodeAnnouncementEventData(event: {
|
|
43
|
+
schemeId: bigint;
|
|
44
|
+
stealthAddress: Uint8Array;
|
|
45
|
+
caller: Uint8Array | PublicKey;
|
|
46
|
+
ephemeralPubKey: Uint8Array;
|
|
47
|
+
metadata: Uint8Array;
|
|
48
|
+
}): Uint8Array;
|
|
49
|
+
/**
|
|
50
|
+
* Decode a single `Announcement` event payload (the bytes after the `Program data: ` base64
|
|
51
|
+
* decode). Returns `null` when the discriminator does not match or the buffer is malformed.
|
|
52
|
+
*/
|
|
53
|
+
export declare function decodeAnnouncementEventData(data: Uint8Array): DecodedAnnouncementEvent | null;
|
|
54
|
+
/** Map a decoded event to the chain-neutral {@link Announcement} shape (Solana). */
|
|
55
|
+
export declare function eventToAnnouncement(event: DecodedAnnouncementEvent, provenance?: {
|
|
56
|
+
txHash?: string;
|
|
57
|
+
cursor?: bigint;
|
|
58
|
+
}): Announcement;
|
|
59
|
+
/**
|
|
60
|
+
* Decode every `Announcement` event in a transaction's log messages into chain-neutral
|
|
61
|
+
* {@link Announcement}s. Non-matching `Program data:` lines (other events) are skipped, as
|
|
62
|
+
* are events whose scheme id is not {@link SCHEME_ID_SECP256K1}.
|
|
63
|
+
*/
|
|
64
|
+
export declare function decodeAnnouncementLogs(logs: string[], provenance?: {
|
|
65
|
+
txHash?: string;
|
|
66
|
+
cursor?: bigint;
|
|
67
|
+
}): Announcement[];
|
|
68
|
+
/**
|
|
69
|
+
* Fetch historical announcements by walking recent signatures for the announcer program and
|
|
70
|
+
* decoding each transaction's logs. Returns chain-neutral {@link Announcement}s in signature
|
|
71
|
+
* order (newest first, as returned by the RPC).
|
|
72
|
+
*/
|
|
73
|
+
export declare function fetchAnnouncementsRange(connection: Connection, params: {
|
|
74
|
+
announcerProgramId: PublicKey;
|
|
75
|
+
/** Max signatures to scan (RPC `getSignaturesForAddress` limit; default 1000). */
|
|
76
|
+
limit?: number;
|
|
77
|
+
/** Start searching backwards from this signature (pagination). */
|
|
78
|
+
before?: string;
|
|
79
|
+
/** Search until this signature (pagination). */
|
|
80
|
+
until?: string;
|
|
81
|
+
commitment?: Finality;
|
|
82
|
+
}): Promise<Announcement[]>;
|
|
83
|
+
/**
|
|
84
|
+
* Subscribe to new announcer logs and decode them. Returns an unsubscribe function.
|
|
85
|
+
* `cursor` (slot) is not provided by `onLogs`; callers needing the slot should re-fetch by
|
|
86
|
+
* signature.
|
|
87
|
+
*/
|
|
88
|
+
export declare function watchAnnouncements(connection: Connection, params: {
|
|
89
|
+
announcerProgramId: PublicKey;
|
|
90
|
+
commitment?: Finality;
|
|
91
|
+
} & AnnouncementHandlers): () => void;
|
|
92
|
+
//# sourceMappingURL=announcer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"announcer.d.ts","sourceRoot":"","sources":["../src/announcer.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EACL,UAAU,EACV,SAAS,EACT,sBAAsB,EACtB,KAAK,QAAQ,EACd,MAAM,iBAAiB,CAAC;AACzB,OAAO,EACL,KAAK,YAAY,EAEjB,KAAK,oBAAoB,EAE1B,MAAM,qBAAqB,CAAC;AAW7B,6DAA6D;AAC7D,MAAM,WAAW,wBAAwB;IACvC,QAAQ,EAAE,MAAM,CAAC;IACjB,yFAAyF;IACzF,cAAc,EAAE,UAAU,CAAC;IAC3B,2CAA2C;IAC3C,MAAM,EAAE,UAAU,CAAC;IACnB,2DAA2D;IAC3D,eAAe,EAAE,UAAU,CAAC;IAC5B,6DAA6D;IAC7D,QAAQ,EAAE,UAAU,CAAC;CACtB;AAED;;GAEG;AACH,wBAAgB,wBAAwB,CAAC,MAAM,EAAE;IAC/C,kBAAkB,EAAE,SAAS,CAAC;IAC9B,MAAM,EAAE,SAAS,CAAC;IAClB,uFAAuF;IACvF,cAAc,EAAE,UAAU,CAAC;IAC3B,yDAAyD;IACzD,eAAe,EAAE,UAAU,CAAC;IAC5B,oDAAoD;IACpD,QAAQ,EAAE,UAAU,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB,GAAG,sBAAsB,CAazB;AAED;;;GAGG;AACH,wBAAgB,2BAA2B,CAAC,KAAK,EAAE;IACjD,QAAQ,EAAE,MAAM,CAAC;IACjB,cAAc,EAAE,UAAU,CAAC;IAC3B,MAAM,EAAE,UAAU,GAAG,SAAS,CAAC;IAC/B,eAAe,EAAE,UAAU,CAAC;IAC5B,QAAQ,EAAE,UAAU,CAAC;CACtB,GAAG,UAAU,CAgBb;AAUD;;;GAGG;AACH,wBAAgB,2BAA2B,CACzC,IAAI,EAAE,UAAU,GACf,wBAAwB,GAAG,IAAI,CAajC;AAaD,oFAAoF;AACpF,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,wBAAwB,EAC/B,UAAU,GAAE;IAAE,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAO,GACpD,YAAY,CAUd;AAED;;;;GAIG;AACH,wBAAgB,sBAAsB,CACpC,IAAI,EAAE,MAAM,EAAE,EACd,UAAU,GAAE;IAAE,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAO,GACpD,YAAY,EAAE,CAYhB;AAED;;;;GAIG;AACH,wBAAsB,uBAAuB,CAC3C,UAAU,EAAE,UAAU,EACtB,MAAM,EAAE;IACN,kBAAkB,EAAE,SAAS,CAAC;IAC9B,kFAAkF;IAClF,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,kEAAkE;IAClE,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,gDAAgD;IAChD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE,QAAQ,CAAC;CACvB,GACA,OAAO,CAAC,YAAY,EAAE,CAAC,CAyBzB;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAChC,UAAU,EAAE,UAAU,EACtB,MAAM,EAAE;IACN,kBAAkB,EAAE,SAAS,CAAC;IAC9B,UAAU,CAAC,EAAE,QAAQ,CAAC;CACvB,GAAG,oBAAoB,GACvB,MAAM,IAAI,CAoBZ"}
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `StealthAddressAnnouncer` (Solana) — `announce` instruction building, `Announcement`
|
|
3
|
+
* event decoding from transaction logs, historical range fetch, and live subscription.
|
|
4
|
+
*
|
|
5
|
+
* The on-chain `Announcement` event (Anchor `emit!`) is surfaced in transaction logs as a
|
|
6
|
+
* `Program data: <base64>` line: an 8-byte event discriminator followed by the Borsh body
|
|
7
|
+
* `{ scheme_id: u64, stealth_address: Vec<u8>, caller: Pubkey, ephemeral_pub_key: Vec<u8>,
|
|
8
|
+
* metadata: Vec<u8> }`. See `solana/target/idl/stealth_announcer.json`.
|
|
9
|
+
*/
|
|
10
|
+
import { PublicKey, TransactionInstruction, } from "@solana/web3.js";
|
|
11
|
+
import { WORMHOLE_CHAIN_SOLANA, } from "@opaquecash/adapter";
|
|
12
|
+
import { ByteReader, bytesToHex, concatBytes, u64le, vecU8 } from "./bytes.js";
|
|
13
|
+
import { ANNOUNCE_DISCRIMINATOR, ANNOUNCEMENT_EVENT_DISCRIMINATOR, SCHEME_ID_SECP256K1, } from "./programs.js";
|
|
14
|
+
const PROGRAM_DATA_PREFIX = "Program data: ";
|
|
15
|
+
const EPHEMERAL_PUBKEY_LEN = 33;
|
|
16
|
+
/**
|
|
17
|
+
* Build an `announce` instruction. `caller` signs and pays; the app's wallet layer submits.
|
|
18
|
+
*/
|
|
19
|
+
export function buildAnnounceInstruction(params) {
|
|
20
|
+
const data = concatBytes(ANNOUNCE_DISCRIMINATOR, u64le(params.schemeId ?? SCHEME_ID_SECP256K1), vecU8(params.stealthAddress), vecU8(params.ephemeralPubKey), vecU8(params.metadata));
|
|
21
|
+
return new TransactionInstruction({
|
|
22
|
+
programId: params.announcerProgramId,
|
|
23
|
+
keys: [{ pubkey: params.caller, isSigner: true, isWritable: true }],
|
|
24
|
+
data: Buffer.from(data),
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Encode the `Announcement` event body the way the program emits it (8-byte discriminator
|
|
29
|
+
* + Borsh). Useful for fixtures and round-trip tests.
|
|
30
|
+
*/
|
|
31
|
+
export function encodeAnnouncementEventData(event) {
|
|
32
|
+
const caller = event.caller instanceof PublicKey
|
|
33
|
+
? event.caller.toBytes()
|
|
34
|
+
: event.caller;
|
|
35
|
+
if (caller.length !== 32) {
|
|
36
|
+
throw new Error("caller must be a 32-byte pubkey");
|
|
37
|
+
}
|
|
38
|
+
return concatBytes(ANNOUNCEMENT_EVENT_DISCRIMINATOR, u64le(event.schemeId), vecU8(event.stealthAddress), caller, vecU8(event.ephemeralPubKey), vecU8(event.metadata));
|
|
39
|
+
}
|
|
40
|
+
function discriminatorMatches(data, disc) {
|
|
41
|
+
if (data.length < disc.length)
|
|
42
|
+
return false;
|
|
43
|
+
for (let i = 0; i < disc.length; i++) {
|
|
44
|
+
if (data[i] !== disc[i])
|
|
45
|
+
return false;
|
|
46
|
+
}
|
|
47
|
+
return true;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Decode a single `Announcement` event payload (the bytes after the `Program data: ` base64
|
|
51
|
+
* decode). Returns `null` when the discriminator does not match or the buffer is malformed.
|
|
52
|
+
*/
|
|
53
|
+
export function decodeAnnouncementEventData(data) {
|
|
54
|
+
if (!discriminatorMatches(data, ANNOUNCEMENT_EVENT_DISCRIMINATOR))
|
|
55
|
+
return null;
|
|
56
|
+
try {
|
|
57
|
+
const r = new ByteReader(data, ANNOUNCEMENT_EVENT_DISCRIMINATOR.length);
|
|
58
|
+
const schemeId = r.readU64();
|
|
59
|
+
const stealthAddress = r.readVecU8();
|
|
60
|
+
const caller = r.readBytes(32);
|
|
61
|
+
const ephemeralPubKey = r.readVecU8();
|
|
62
|
+
const metadata = r.readVecU8();
|
|
63
|
+
return { schemeId, stealthAddress, caller, ephemeralPubKey, metadata };
|
|
64
|
+
}
|
|
65
|
+
catch {
|
|
66
|
+
return null;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
function base64ToBytes(b64) {
|
|
70
|
+
if (typeof atob === "function") {
|
|
71
|
+
const bin = atob(b64);
|
|
72
|
+
const out = new Uint8Array(bin.length);
|
|
73
|
+
for (let i = 0; i < bin.length; i++)
|
|
74
|
+
out[i] = bin.charCodeAt(i);
|
|
75
|
+
return out;
|
|
76
|
+
}
|
|
77
|
+
// Node fallback.
|
|
78
|
+
return new Uint8Array(Buffer.from(b64, "base64"));
|
|
79
|
+
}
|
|
80
|
+
/** Map a decoded event to the chain-neutral {@link Announcement} shape (Solana). */
|
|
81
|
+
export function eventToAnnouncement(event, provenance = {}) {
|
|
82
|
+
return {
|
|
83
|
+
stealthAddress: ("0x" + bytesToHex(event.stealthAddress)),
|
|
84
|
+
ephemeralPubKey: event.ephemeralPubKey,
|
|
85
|
+
viewTag: event.metadata.length > 0 ? event.metadata[0] : 0,
|
|
86
|
+
metadata: event.metadata,
|
|
87
|
+
chainId: WORMHOLE_CHAIN_SOLANA,
|
|
88
|
+
txHash: provenance.txHash,
|
|
89
|
+
cursor: provenance.cursor,
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Decode every `Announcement` event in a transaction's log messages into chain-neutral
|
|
94
|
+
* {@link Announcement}s. Non-matching `Program data:` lines (other events) are skipped, as
|
|
95
|
+
* are events whose scheme id is not {@link SCHEME_ID_SECP256K1}.
|
|
96
|
+
*/
|
|
97
|
+
export function decodeAnnouncementLogs(logs, provenance = {}) {
|
|
98
|
+
const out = [];
|
|
99
|
+
for (const log of logs) {
|
|
100
|
+
if (!log.startsWith(PROGRAM_DATA_PREFIX))
|
|
101
|
+
continue;
|
|
102
|
+
const data = base64ToBytes(log.slice(PROGRAM_DATA_PREFIX.length));
|
|
103
|
+
const event = decodeAnnouncementEventData(data);
|
|
104
|
+
if (!event)
|
|
105
|
+
continue;
|
|
106
|
+
if (event.schemeId !== SCHEME_ID_SECP256K1)
|
|
107
|
+
continue;
|
|
108
|
+
if (event.ephemeralPubKey.length !== EPHEMERAL_PUBKEY_LEN)
|
|
109
|
+
continue;
|
|
110
|
+
out.push(eventToAnnouncement(event, provenance));
|
|
111
|
+
}
|
|
112
|
+
return out;
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Fetch historical announcements by walking recent signatures for the announcer program and
|
|
116
|
+
* decoding each transaction's logs. Returns chain-neutral {@link Announcement}s in signature
|
|
117
|
+
* order (newest first, as returned by the RPC).
|
|
118
|
+
*/
|
|
119
|
+
export async function fetchAnnouncementsRange(connection, params) {
|
|
120
|
+
const commitment = params.commitment ?? "confirmed";
|
|
121
|
+
const signatures = await connection.getSignaturesForAddress(params.announcerProgramId, { limit: params.limit ?? 1000, before: params.before, until: params.until }, commitment);
|
|
122
|
+
const out = [];
|
|
123
|
+
for (const sig of signatures) {
|
|
124
|
+
if (sig.err)
|
|
125
|
+
continue;
|
|
126
|
+
const tx = await connection.getTransaction(sig.signature, {
|
|
127
|
+
commitment,
|
|
128
|
+
maxSupportedTransactionVersion: 0,
|
|
129
|
+
});
|
|
130
|
+
const logs = tx?.meta?.logMessages;
|
|
131
|
+
if (!logs)
|
|
132
|
+
continue;
|
|
133
|
+
out.push(...decodeAnnouncementLogs(logs, {
|
|
134
|
+
txHash: sig.signature,
|
|
135
|
+
cursor: BigInt(sig.slot),
|
|
136
|
+
}));
|
|
137
|
+
}
|
|
138
|
+
return out;
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* Subscribe to new announcer logs and decode them. Returns an unsubscribe function.
|
|
142
|
+
* `cursor` (slot) is not provided by `onLogs`; callers needing the slot should re-fetch by
|
|
143
|
+
* signature.
|
|
144
|
+
*/
|
|
145
|
+
export function watchAnnouncements(connection, params) {
|
|
146
|
+
const id = connection.onLogs(params.announcerProgramId, (logInfo) => {
|
|
147
|
+
if (logInfo.err)
|
|
148
|
+
return;
|
|
149
|
+
try {
|
|
150
|
+
for (const a of decodeAnnouncementLogs(logInfo.logs, {
|
|
151
|
+
txHash: logInfo.signature,
|
|
152
|
+
})) {
|
|
153
|
+
params.onAnnouncement(a);
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
catch (e) {
|
|
157
|
+
params.onError?.(e instanceof Error ? e : new Error(String(e)));
|
|
158
|
+
}
|
|
159
|
+
}, params.commitment ?? "confirmed");
|
|
160
|
+
return () => {
|
|
161
|
+
void connection.removeOnLogsListener(id);
|
|
162
|
+
};
|
|
163
|
+
}
|
|
164
|
+
//# sourceMappingURL=announcer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"announcer.js","sourceRoot":"","sources":["../src/announcer.ts"],"names":[],"mappings":"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"}
|
package/dist/bytes.d.ts
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Little-endian integer codecs and byte helpers for Borsh-style Solana instruction data
|
|
3
|
+
* and Anchor event decoding. Kept dependency-light (DataView + `@noble/hashes/utils`) so
|
|
4
|
+
* the decoders run unchanged in Node and the browser.
|
|
5
|
+
*/
|
|
6
|
+
import { concatBytes } from "@noble/hashes/utils";
|
|
7
|
+
export { concatBytes };
|
|
8
|
+
/** Lowercase hex without `0x` prefix. */
|
|
9
|
+
export declare function bytesToHex(b: Uint8Array): string;
|
|
10
|
+
/** Parse hex (with or without `0x`) into bytes. */
|
|
11
|
+
export declare function hexToBytes(hex: string): Uint8Array;
|
|
12
|
+
/** Encode a u64 as 8 little-endian bytes. */
|
|
13
|
+
export declare function u64le(value: bigint): Uint8Array;
|
|
14
|
+
/** Encode a u32 as 4 little-endian bytes. */
|
|
15
|
+
export declare function u32le(value: number): Uint8Array;
|
|
16
|
+
/** Encode a Borsh `Vec<u8>` (u32 LE length prefix + bytes). */
|
|
17
|
+
export declare function vecU8(bytes: Uint8Array): Uint8Array;
|
|
18
|
+
/** A cursor into a byte buffer for sequential little-endian reads. */
|
|
19
|
+
export declare class ByteReader {
|
|
20
|
+
private readonly data;
|
|
21
|
+
private readonly view;
|
|
22
|
+
private offset;
|
|
23
|
+
constructor(data: Uint8Array, startOffset?: number);
|
|
24
|
+
get position(): number;
|
|
25
|
+
get remaining(): number;
|
|
26
|
+
skip(n: number): void;
|
|
27
|
+
readU16(): number;
|
|
28
|
+
readU32(): number;
|
|
29
|
+
readU64(): bigint;
|
|
30
|
+
/** Read `len` raw bytes (copied out). */
|
|
31
|
+
readBytes(len: number): Uint8Array;
|
|
32
|
+
/** Read a Borsh `Vec<u8>` (u32 LE length prefix + bytes). */
|
|
33
|
+
readVecU8(): Uint8Array;
|
|
34
|
+
}
|
|
35
|
+
//# sourceMappingURL=bytes.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bytes.d.ts","sourceRoot":"","sources":["../src/bytes.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAGL,WAAW,EACZ,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EAAE,WAAW,EAAE,CAAC;AAEvB,yCAAyC;AACzC,wBAAgB,UAAU,CAAC,CAAC,EAAE,UAAU,GAAG,MAAM,CAEhD;AAED,mDAAmD;AACnD,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,UAAU,CAElD;AAED,6CAA6C;AAC7C,wBAAgB,KAAK,CAAC,KAAK,EAAE,MAAM,GAAG,UAAU,CAI/C;AAED,6CAA6C;AAC7C,wBAAgB,KAAK,CAAC,KAAK,EAAE,MAAM,GAAG,UAAU,CAI/C;AAED,+DAA+D;AAC/D,wBAAgB,KAAK,CAAC,KAAK,EAAE,UAAU,GAAG,UAAU,CAEnD;AAED,sEAAsE;AACtE,qBAAa,UAAU;IACrB,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAa;IAClC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAW;IAChC,OAAO,CAAC,MAAM,CAAS;gBAEX,IAAI,EAAE,UAAU,EAAE,WAAW,SAAI;IAM7C,IAAI,QAAQ,IAAI,MAAM,CAErB;IAED,IAAI,SAAS,IAAI,MAAM,CAEtB;IAED,IAAI,CAAC,CAAC,EAAE,MAAM,GAAG,IAAI;IAIrB,OAAO,IAAI,MAAM;IAMjB,OAAO,IAAI,MAAM;IAMjB,OAAO,IAAI,MAAM;IAMjB,yCAAyC;IACzC,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,UAAU;IAMlC,6DAA6D;IAC7D,SAAS,IAAI,UAAU;CAIxB"}
|