pangu-sdk 0.1.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.
@@ -0,0 +1,415 @@
1
+ import { PublicKey, Connection, TransactionInstruction } from '@solana/web3.js';
2
+ import { Idl } from '@anchor-lang/core';
3
+ import { S as Sale, B as BuyerRecord, L as ListSalesOptions } from './accounts-BuD-oCcr.js';
4
+ export { F as FeedId, P as PanguInputError, a as PanguLayoutError, b as attestationAddress, c as buyerRecordAddress, d as dbcBaseVaultAddress, e as decodeBuyerRecord, f as decodeSale, g as extraAccountListAddress, h as feedIdBytes, i as feedIdHex, j as getBuyerRecord, k as getSale, l as isSaleRunning, m as listBuyerRecords, n as listSales, p as priceFeedAddress, s as saleRulesAddress } from './accounts-BuD-oCcr.js';
5
+ export { A as ApproveBuyerInput, C as CloseBuyerRecordInput, c as CreateSaleInput, O as OpenBuyerRecordInput, d as PANGU_ERRORS, e as PanguError, a as PanguErrorName, P as PriceBandInput, b as PriceReading, f as PriceUpdate, R as RevokeBuyerInput, g as approveBuyerInstruction, h as closeBuyerRecordInstruction, i as createSaleInstruction, j as decodePriceUpdate, k as explainPanguError, o as openBuyerRecordInstruction, p as panguErrorFromLogs, r as readPrice, l as revokeBuyerInstruction } from './feed-Zwu1irEx.js';
6
+ export { TOKEN_2022_PROGRAM_ID } from '@solana/spl-token';
7
+
8
+ /**
9
+ * The generated interface of the Pangu program, copied from the program's build
10
+ * by `npm run sync-idl`. Everything else in this package is derived from it, so
11
+ * a rebuilt program cannot leave a stale discriminator or error code behind.
12
+ */
13
+ declare const PANGU_IDL: Idl;
14
+ declare const PANGU_PROGRAM_ID: PublicKey;
15
+ /** Meteora's Dynamic Bonding Curve. Source: programs/pangu/src/dbc.rs. */
16
+ declare const DBC_PROGRAM_ID: PublicKey;
17
+ /** The Solana Attestation Service. Source: programs/pangu/src/sas.rs. */
18
+ declare const SAS_PROGRAM_ID: PublicKey;
19
+ /**
20
+ * Pyth's price feed program. Every price feed account is a program address of
21
+ * this program over a shard id and a feed id, so a sale can name the address
22
+ * before anybody has ever refreshed it.
23
+ * Source: programs/pangu/src/price.rs, PRICE_FEED_PROGRAM_ID.
24
+ */
25
+ declare const PYTH_PRICE_FEED_PROGRAM_ID: PublicKey;
26
+ /**
27
+ * Pyth's receiver program, the only program that can write a price feed
28
+ * account, and only after checking the Wormhole guardians' signatures.
29
+ * Source: programs/pangu/src/price.rs, RECEIVER_PROGRAM_ID.
30
+ */
31
+ declare const PYTH_RECEIVER_PROGRAM_ID: PublicKey;
32
+ /**
33
+ * The Pyth shard Pangu refreshes. A shard is a second copy of the same feed at
34
+ * a second address, so a sale depends on a price Pangu's own refresher keeps
35
+ * fresh rather than on the sponsored one.
36
+ * Source: programs/pangu/src/price.rs, PANGU_SHARD_ID.
37
+ */
38
+ declare const PANGU_SHARD_ID = 7700;
39
+
40
+ /**
41
+ * The SaleRules layouts this package reads. Source: state.rs,
42
+ * SALE_RULES_OLDEST_READABLE_VERSION to SALE_RULES_LAYOUT_VERSION. Version 2
43
+ * added the paying token and the end of the offering period in what used to be
44
+ * spare bytes, so a version 1 account is the same size with every older field
45
+ * in place. An account carrying any other number was written by a different
46
+ * build of the program, so every field behind the version byte may sit
47
+ * somewhere else.
48
+ */
49
+ declare const SALE_RULES_LAYOUT_VERSIONS: ReadonlySet<number>;
50
+ declare const ACCESS_MODE: {
51
+ readonly open: 0;
52
+ readonly issuerList: 1;
53
+ readonly verifierCredential: 2;
54
+ };
55
+ type AccessMode = (typeof ACCESS_MODE)[keyof typeof ACCESS_MODE];
56
+ /**
57
+ * The seed prefixes the program and its neighbours derive addresses from.
58
+ * Source: state.rs (sale, buyer, extra-account-metas), sas.rs (attestation),
59
+ * the attestation service source (credential, schema), dbc.rs (token_vault).
60
+ */
61
+ declare const SEEDS: {
62
+ readonly sale: "sale";
63
+ readonly buyer: "buyer";
64
+ readonly extraAccountMetas: "extra-account-metas";
65
+ readonly attestation: "attestation";
66
+ readonly credential: "credential";
67
+ readonly schema: "schema";
68
+ readonly dbcTokenVault: "token_vault";
69
+ };
70
+ /**
71
+ * The limits the program itself enforces. Each one names the Rust constant or
72
+ * check it copies, so a change on chain has one place to land here.
73
+ */
74
+ declare const LIMITS: {
75
+ /** price.rs MAX_BAND_BPS: half again over the live stock price. */
76
+ readonly maxBandBps: 5000;
77
+ readonly minBandBps: 1;
78
+ /** price.rs MAX_PRICE_AGE_SECS, and create_sale.rs check_band takes 1..=3600. */
79
+ readonly maxPriceAgeSecs: 3600;
80
+ readonly minPriceAgeSecs: 1;
81
+ /** price.rs MAX_CONF_BPS: ten percent, and check_band takes 1..=1000. */
82
+ readonly maxConfBps: 1000;
83
+ readonly minConfBps: 1;
84
+ /** price.rs MAX_DECIMALS. */
85
+ readonly maxDecimals: 18;
86
+ /** Every Pyth feed id is 32 bytes. */
87
+ readonly feedIdLength: 32;
88
+ /** A Pyth shard id is a u16, which is what the address seed holds. */
89
+ readonly maxShard: 65535;
90
+ /** u64 raw token units, the widest cap the program can hold. */
91
+ readonly maxCap: bigint;
92
+ };
93
+ /**
94
+ * The dollar tokens a banded sale can be paid in on `network`, in the order the
95
+ * program lists them. A fresh array each call, so a caller cannot change the
96
+ * list another caller reads.
97
+ *
98
+ * Covers the exact addresses the program checks. Does not say whether a listed
99
+ * stablecoin still holds its peg. Throws for any network other than "devnet" or
100
+ * "mainnet", because guessing a list would let a ceiling through the program
101
+ * then refuses.
102
+ */
103
+ declare function dollarMints(network: "devnet" | "mainnet"): PublicKey[];
104
+
105
+ /**
106
+ * Every price in this package is a dollar amount scaled by 1e18, which is the
107
+ * one scale the program compares on (PRICE_SCALE_DECIMALS in price.rs).
108
+ * Working in that scale means the band comparison never rounds twice.
109
+ */
110
+ declare const DOLLAR_SCALE: bigint;
111
+ /**
112
+ * A Pyth price turned into dollars scaled by 1e18, the way
113
+ * `stock_price_1e18` does it on chain.
114
+ *
115
+ * Pyth publishes a whole number and an exponent, and the real price is the
116
+ * number times ten to that exponent. A price at a finer scale than 1e18 rounds
117
+ * down, exactly as the program's integer division does, and a zero is what the
118
+ * program then refuses.
119
+ *
120
+ * Throws PanguInputError for a price that is not above zero, or an exponent no
121
+ * dollar price can use.
122
+ */
123
+ declare function stockPriceDollars(price: bigint, exponent: number): bigint;
124
+ /**
125
+ * Pyth's confidence interval as basis points of the price itself, rounded UP.
126
+ *
127
+ * Rounded up, so half a basis point of doubt counts as one and never as none.
128
+ * The same arithmetic as `require_confidence` in price.rs.
129
+ *
130
+ * Throws PanguInputError for a price that is not above zero.
131
+ */
132
+ declare function confidenceBps(price: bigint, conf: bigint): bigint;
133
+ /**
134
+ * The curve's price in dollars per whole token, scaled by 1e18 and rounded UP.
135
+ *
136
+ * `sqrtPrice` is DBC's Q64.64 square root of quote raw units per base raw unit,
137
+ * so the price is `(sqrtPrice / 2^64)^2` shifted by the two mints' decimals.
138
+ * Rounding goes up, always, matching `curve_price_ceil_1e18` in
139
+ * programs/pangu/src/price.rs, so a fraction of a unit can never be the reason
140
+ * a buy looks allowed here and is refused on chain.
141
+ *
142
+ * Throws PanguInputError for a negative square root price or for decimals past
143
+ * the program's own limit of 18.
144
+ */
145
+ declare function curvePriceDollars(sqrtPrice: bigint, baseDecimals: number, quoteDecimals: number): bigint;
146
+ /** The part of a sale's rules the ceiling is worked out from. */
147
+ interface BandRules {
148
+ bandBps: number;
149
+ }
150
+ /**
151
+ * The highest curve price this sale allows, scaled by 1e18 and rounded DOWN.
152
+ *
153
+ * Rounding down here and up in `curvePriceDollars` is the program's own pairing
154
+ * (`band_ceiling_floor_1e18`): a buy that lands exactly on the ceiling passes,
155
+ * and nothing between the two roundings slips through.
156
+ *
157
+ * Throws PanguInputError when the sale has no band or the stock price is not
158
+ * above zero, which is what the program treats as an unusable price.
159
+ */
160
+ declare function priceCeiling(sale: BandRules, stockPrice: bigint): bigint;
161
+ /** The same 1e18 scaled number as dollars, for display only. */
162
+ declare function dollars(scaled: bigint): number;
163
+
164
+ /** How concentrated a sale is right now, from the records themselves. */
165
+ interface SaleStanding {
166
+ /** Wallets holding more than zero net of what they sold back. */
167
+ buyers: number;
168
+ /** Everything the pool has sold, net of sells, in raw token units. */
169
+ totalNetBought: bigint;
170
+ /** The wallet holding the most, or null when nothing has been sold. */
171
+ largestWallet: PublicKey | null;
172
+ largestNetBought: bigint;
173
+ /** The largest wallet's share of everything sold, 0 to 1. */
174
+ largestShare: number;
175
+ /** What one wallet's cap is worth as a share of everything sold, 0 to 1 and above. */
176
+ capShare: number;
177
+ /**
178
+ * True once the sale's offering period has ended: from then on the hook
179
+ * counts nothing and the token moves freely. Always false for a sale with no
180
+ * end, which includes every version 1 sale.
181
+ */
182
+ offeringOver: boolean;
183
+ }
184
+ /**
185
+ * Works out how concentrated a sale is from its records.
186
+ *
187
+ * The counts come from the records, not from the rules account's own running
188
+ * totals, so what the app shows is the sum of the accounts a judge can open.
189
+ * Records belonging to another sale are refused rather than ignored: silently
190
+ * dropping them would understate the largest holder.
191
+ *
192
+ * `now` is the Unix second to judge the offering period against. Pass the
193
+ * chain's clock when you have it, because that is the clock the hook reads and
194
+ * a browser's can be minutes out; without it this machine's clock stands in,
195
+ * which can only misjudge the end within that drift.
196
+ */
197
+ declare function saleStanding(sale: Sale, records: BuyerRecord[], now?: number): SaleStanding;
198
+
199
+ /** A sale token's name, symbol and metadata link, as the mint itself carries them. */
200
+ interface SaleTokenInfo {
201
+ name: string;
202
+ symbol: string;
203
+ uri: string;
204
+ }
205
+ /**
206
+ * The sale token's name, symbol and metadata link.
207
+ *
208
+ * DBC writes these into the Token-2022 metadata extension on the mint itself,
209
+ * with the mint's metadata pointer naming the mint, when the pool opens. Only
210
+ * that shape is read: a pointer naming some other account means the copy on the
211
+ * mint is not the one the token claims, so the answer is null rather than a
212
+ * guess. Null too when the mint does not exist, is not a Token-2022 mint, or
213
+ * carries no metadata.
214
+ *
215
+ * The text is whatever the issuer typed at launch and nothing checks it, so
216
+ * show it as a label, never trust it as an identity: two sales can carry the
217
+ * same name. The mint address is what identifies a sale.
218
+ */
219
+ declare function saleTokenInfo(connection: Connection, mint: PublicKey): Promise<SaleTokenInfo | null>;
220
+ /** One sale as a list page shows it. */
221
+ interface SaleDirectoryEntry {
222
+ mint: PublicKey;
223
+ pool: PublicKey;
224
+ /** From the mint's metadata. Null when the mint carries none this package reads. */
225
+ name: string | null;
226
+ symbol: string | null;
227
+ /** True while the mint still names Pangu as its transfer hook, as `isSaleRunning`. */
228
+ running: boolean;
229
+ /**
230
+ * True once the curve is full, read from DBC's own record on the pool. Null
231
+ * when the pool the rules name cannot be read as the transfer hook pool
232
+ * selling this mint.
233
+ */
234
+ graduated: boolean | null;
235
+ /** True once the offering period has ended by the chain's clock. */
236
+ offeringOver: boolean;
237
+ hasBand: boolean;
238
+ accessMode: number;
239
+ quoteMint: PublicKey | null;
240
+ endsAt: number | null;
241
+ buyers: number;
242
+ issuer: PublicKey;
243
+ /** The full rules, with the token's decimals filled from the mint when the rules store none. */
244
+ sale: Sale;
245
+ }
246
+ /**
247
+ * Every Pangu sale on the chain with what a list page shows: the token's name
248
+ * and symbol, whether it is running, graduated or past its offering period,
249
+ * and the headline rules.
250
+ *
251
+ * Reads are batched: one scan for the rules (see `listSales`, whose skipping
252
+ * and `onSkipped` apply here unchanged), then every mint and pool plus the
253
+ * Clock sysvar in calls of 100 addresses. Fifty sales cost three calls. The
254
+ * scan and the batch are separate calls, so a sale that changes between them
255
+ * is shown as of two nearby moments.
256
+ *
257
+ * Nothing about one sale can stop the others being listed: a mint that cannot
258
+ * be read shows no name and not running, and a pool that cannot be read shows
259
+ * `graduated` as null. Throws only when the node refuses a call.
260
+ */
261
+ declare function saleDirectory(connection: Connection, options?: ListSalesOptions): Promise<SaleDirectoryEntry[]>;
262
+
263
+ /**
264
+ * The schema a Pangu sale is written for: one byte, named "verified".
265
+ *
266
+ * Pangu never reads an attestation's data. It reads who the attestation is
267
+ * about, who signed it, and when it runs out (programs/pangu/src/sas.rs), so
268
+ * the smallest shape the service accepts is the right one. The service checks
269
+ * every attestation's data against its schema's layout, which is why an
270
+ * attestation defaults to the one byte this layout expects.
271
+ */
272
+ declare const VERIFIED_SCHEMA: {
273
+ readonly layout: readonly number[];
274
+ readonly fieldNames: readonly string[];
275
+ readonly attestationData: readonly number[];
276
+ };
277
+ interface CreateCredentialInput {
278
+ /** Pays the rent. May be the authority. */
279
+ payer: PublicKey;
280
+ /** Runs the credential and signs. The address is derived from it and the name. */
281
+ authority: PublicKey;
282
+ name: string;
283
+ /** The keys allowed to attest under this credential, one to 64 of them. */
284
+ signers: PublicKey[];
285
+ }
286
+ interface CreateSchemaInput {
287
+ payer: PublicKey;
288
+ /** The credential's authority, who alone can add a schema to it. */
289
+ authority: PublicKey;
290
+ credential: PublicKey;
291
+ name: string;
292
+ description: string;
293
+ /** The service's layout codes, one per field. Defaults to VERIFIED_SCHEMA. */
294
+ layout?: readonly number[];
295
+ fieldNames?: readonly string[];
296
+ }
297
+ interface CreateAttestationInput {
298
+ payer: PublicKey;
299
+ /** One of the credential's signers. Pangu checks it is still on the list at every buy. */
300
+ authorizedSigner: PublicKey;
301
+ credential: PublicKey;
302
+ schema: PublicKey;
303
+ /**
304
+ * The buyer. Used as the attestation's nonce, which is the convention Pangu
305
+ * requires: the hook derives the attestation address from the buying wallet
306
+ * and refuses an attestation about anyone else.
307
+ */
308
+ wallet: PublicKey;
309
+ /** Unix seconds at which the attestation runs out. Zero means it never does. */
310
+ expiry: number;
311
+ /** Bytes matching the schema's layout. Defaults to VERIFIED_SCHEMA's one byte. */
312
+ data?: Uint8Array | readonly number[];
313
+ }
314
+ /** A credential's address. Seeds "credential", the authority and the name. */
315
+ declare function credentialAddress(authority: PublicKey, name: string): PublicKey;
316
+ /** A schema's first version. Seeds "schema", the credential, the name and the version byte. */
317
+ declare function schemaAddress(credential: PublicKey, name: string): PublicKey;
318
+ /**
319
+ * Opens a credential on the attestation service: a named verifier with a list
320
+ * of keys allowed to attest under it.
321
+ *
322
+ * Throws PanguInputError for an empty or over-long name, no signers, a repeated
323
+ * signer, or more signers than Pangu will read. Sends nothing.
324
+ */
325
+ declare function createCredentialInstruction(input: CreateCredentialInput): TransactionInstruction;
326
+ /**
327
+ * Opens the first version of a schema under a credential. Only the credential's
328
+ * authority can send it.
329
+ *
330
+ * Throws PanguInputError for an empty or over-long name, an empty layout, a
331
+ * layout code outside one byte, or a field name list that does not match the
332
+ * layout one for one. Sends nothing.
333
+ */
334
+ declare function createSchemaInstruction(input: CreateSchemaInput): TransactionInstruction;
335
+ /**
336
+ * Attests one wallet under a credential and schema, with the wallet as the
337
+ * nonce, so the attestation lands at the one address Pangu's hook derives for
338
+ * that buyer.
339
+ *
340
+ * The expiry is unix seconds; zero means never. The service checks the signer
341
+ * is on the credential's list at this moment and never again, which is why
342
+ * Pangu checks it again on every buy. Throws PanguInputError for a missing key,
343
+ * the all zero wallet, a negative or fractional expiry, or data that is not
344
+ * bytes. Sends nothing.
345
+ */
346
+ declare function createAttestationInstruction(input: CreateAttestationInput): TransactionInstruction;
347
+ interface CloseAttestationInput {
348
+ /** Receives the attestation's rent. The verifier, when the verifier revokes. */
349
+ payer: PublicKey;
350
+ /** One of the credential's signers right now. Not necessarily the one who issued it. */
351
+ authorizedSigner: PublicKey;
352
+ credential: PublicKey;
353
+ schema: PublicKey;
354
+ /** The wallet the attestation is about, which is its nonce. */
355
+ wallet: PublicKey;
356
+ }
357
+ /**
358
+ * Revokes a wallet's credential by closing its attestation, the only
359
+ * revocation the service has. Pangu sees it at the next buy: the account is
360
+ * gone, so the buy is refused with CredentialInvalid.
361
+ *
362
+ * The service pays the attestation's rent to the payer, checks the signer is on
363
+ * the credential's list now, and refuses a tokenized attestation, which needs a
364
+ * different instruction. Throws PanguInputError for a missing key or the all
365
+ * zero wallet. Sends nothing.
366
+ */
367
+ declare function closeAttestationInstruction(input: CloseAttestationInput): TransactionInstruction;
368
+ /**
369
+ * Where a wallet stands with one verifier, judged the way Pangu's hook judges
370
+ * the attestation itself: there and in date, there and run out, or not there.
371
+ */
372
+ type CredentialStanding = "valid" | "expired" | "absent";
373
+ /** One credential a verifier has issued, as `listAttestations` reads it. */
374
+ interface IssuedCredential {
375
+ /** The attestation account. */
376
+ address: PublicKey;
377
+ /** The wallet it is about, read from the nonce. */
378
+ wallet: PublicKey;
379
+ /** The key that signed it into existence. */
380
+ signer: PublicKey;
381
+ /** Unix seconds at which it runs out, or zero for never. */
382
+ expiry: number;
383
+ /**
384
+ * Unix seconds of the transaction that opened this attestation, or null when
385
+ * it was not found in the account's recent history. The service stores no
386
+ * date, so this comes from the transaction history.
387
+ */
388
+ created: number | null;
389
+ /** Judged against the chain's own clock at the time of the read. */
390
+ standing: Exclude<CredentialStanding, "absent">;
391
+ }
392
+ /**
393
+ * Every credential issued under one credential and schema, in no particular
394
+ * order, each judged against the chain's clock.
395
+ *
396
+ * One scan of the service's accounts, filtered by the node on the attestation
397
+ * discriminator, the credential and the schema. An attestation that does not
398
+ * sit at the address its own nonce derives is left out: Pangu's hook would never
399
+ * find it, so it approves nobody. Then, per attestation, a short read of its
400
+ * history for the date it was opened, so the cost grows with the list. An RPC
401
+ * that refuses getProgramAccounts throws rather than returning a short list.
402
+ */
403
+ declare function listAttestations(connection: Connection, credential: PublicKey, schema: PublicKey): Promise<IssuedCredential[]>;
404
+ /**
405
+ * Whether a wallet holds a credential from this verifier right now: valid,
406
+ * expired, or absent. Absent covers revoked, never issued, and anything at the
407
+ * address that is not a well formed attestation about this wallet.
408
+ *
409
+ * Reads the attestation and the chain's clock in one call. Not checked here:
410
+ * whether the key that signed it is still on the credential's list, which
411
+ * Pangu also checks at every buy.
412
+ */
413
+ declare function credentialStatus(connection: Connection, credential: PublicKey, schema: PublicKey, wallet: PublicKey): Promise<CredentialStanding>;
414
+
415
+ export { ACCESS_MODE, type AccessMode, type BandRules, BuyerRecord, type CloseAttestationInput, type CreateAttestationInput, type CreateCredentialInput, type CreateSchemaInput, type CredentialStanding, DBC_PROGRAM_ID, DOLLAR_SCALE, type IssuedCredential, LIMITS, ListSalesOptions, PANGU_IDL, PANGU_PROGRAM_ID, PANGU_SHARD_ID, PYTH_PRICE_FEED_PROGRAM_ID, PYTH_RECEIVER_PROGRAM_ID, SALE_RULES_LAYOUT_VERSIONS, SAS_PROGRAM_ID, SEEDS, Sale, type SaleDirectoryEntry, type SaleStanding, type SaleTokenInfo, VERIFIED_SCHEMA, closeAttestationInstruction, confidenceBps, createAttestationInstruction, createCredentialInstruction, createSchemaInstruction, credentialAddress, credentialStatus, curvePriceDollars, dollarMints, dollars, listAttestations, priceCeiling, saleDirectory, saleStanding, saleTokenInfo, schemaAddress, stockPriceDollars };