@waterx/sdk 2.1.0 → 2.3.1-dev.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 +75 -169
- package/dist/src/client.d.ts +52 -2
- package/dist/src/client.js +76 -6
- package/dist/src/config.d.ts +57 -3
- package/dist/src/config.js +10 -4
- package/dist/src/constants.d.ts +6 -0
- package/dist/src/constants.js +6 -0
- package/dist/src/core/waterx-account.d.ts +31 -0
- package/dist/src/core/waterx-account.js +26 -0
- package/dist/src/fetch.d.ts +110 -0
- package/dist/src/fetch.js +149 -4
- package/dist/src/generated/bucket_v2_framework/account.d.ts +5 -5
- package/dist/src/generated/bucket_v2_framework/double.d.ts +77 -77
- package/dist/src/generated/bucket_v2_framework/float.d.ts +73 -73
- package/dist/src/generated/bucket_v2_framework/liability.d.ts +33 -33
- package/dist/src/generated/bucket_v2_framework/linked_table.d.ts +5 -5
- package/dist/src/generated/bucket_v2_framework/linked_table.js +2 -2
- package/dist/src/generated/bucket_v2_framework/sheet.d.ts +57 -57
- package/dist/src/generated/bucket_v2_framework/sheet.js +5 -11
- package/dist/src/generated/native_custody/custody_vault.d.ts +46 -32
- package/dist/src/generated/native_custody/custody_vault.js +19 -10
- package/dist/src/generated/native_custody/deps/bucket_v2_framework/sheet.js +1 -3
- package/dist/src/generated/native_custody/events.js +1 -2
- package/dist/src/generated/pyth_sponsor_rule/pyth_sponsor_rule.d.ts +7 -7
- package/dist/src/generated/pyth_sponsor_rule/pyth_sponsor_rule.js +1 -2
- package/dist/src/generated/utils/index.d.ts +7 -7
- package/dist/src/generated/utils/index.js +9 -6
- package/dist/src/generated/waterx_account/account.d.ts +124 -71
- package/dist/src/generated/waterx_account/account.js +64 -29
- package/dist/src/generated/waterx_account/deps/bucket_v2_framework/sheet.js +1 -3
- package/dist/src/generated/waterx_account/direct_rule.d.ts +5 -5
- package/dist/src/generated/waterx_account/events.d.ts +10 -0
- package/dist/src/generated/waterx_account/events.js +31 -50
- package/dist/src/generated/waterx_constant_rule/constant_rule.d.ts +68 -0
- package/dist/src/generated/waterx_constant_rule/constant_rule.js +59 -0
- package/dist/src/generated/waterx_constant_rule/deps/bucket_v2_framework/float.d.ts +8 -0
- package/dist/src/generated/waterx_constant_rule/deps/bucket_v2_framework/float.js +10 -0
- package/dist/src/generated/waterx_constant_rule/deps/sui/vec_map.d.ts +36 -0
- package/dist/src/generated/waterx_constant_rule/deps/sui/vec_map.js +27 -0
- package/dist/src/generated/waterx_credit/credit_registry.d.ts +9 -9
- package/dist/src/generated/waterx_credit/credit_registry.js +1 -2
- package/dist/src/generated/waterx_credit/limited_supply.d.ts +17 -17
- package/dist/src/generated/waterx_oracle/aggregator.js +1 -2
- package/dist/src/generated/waterx_oracle/collector.d.ts +17 -17
- package/dist/src/generated/waterx_oracle/collector.js +1 -1
- package/dist/src/generated/waterx_oracle/oracle.d.ts +5 -5
- package/dist/src/generated/waterx_perp/account_data.d.ts +5 -5
- package/dist/src/generated/waterx_perp/account_data.js +1 -2
- package/dist/src/generated/waterx_perp/deps/bucket_v2_framework/sheet.js +1 -3
- package/dist/src/generated/waterx_perp/events.d.ts +181 -181
- package/dist/src/generated/waterx_perp/events.js +87 -173
- package/dist/src/generated/waterx_perp/global_config.d.ts +3 -3
- package/dist/src/generated/waterx_perp/global_config.js +6 -12
- package/dist/src/generated/waterx_perp/keyed_big_vector.d.ts +9 -9
- package/dist/src/generated/waterx_perp/keyed_big_vector.js +1 -2
- package/dist/src/generated/waterx_perp/lp_pool.d.ts +115 -115
- package/dist/src/generated/waterx_perp/lp_pool.js +11 -22
- package/dist/src/generated/waterx_perp/market_config.d.ts +61 -43
- package/dist/src/generated/waterx_perp/market_config.js +29 -22
- package/dist/src/generated/waterx_perp/math.d.ts +7 -7
- package/dist/src/generated/waterx_perp/order_book.d.ts +47 -47
- package/dist/src/generated/waterx_perp/position.d.ts +99 -99
- package/dist/src/generated/waterx_perp/position.js +6 -12
- package/dist/src/generated/waterx_perp/request.d.ts +67 -67
- package/dist/src/generated/waterx_perp/request.js +2 -3
- package/dist/src/generated/waterx_perp/response.d.ts +35 -35
- package/dist/src/generated/waterx_perp/response.js +1 -2
- package/dist/src/generated/waterx_perp/trading.d.ts +303 -179
- package/dist/src/generated/waterx_perp/trading.js +99 -14
- package/dist/src/generated/waterx_perp_view/view.js +5 -10
- package/dist/src/generated/waterx_pyth_rule/pyth_rule.d.ts +5 -5
- package/dist/src/generated/waterx_pyth_rule/pyth_rule.js +1 -2
- package/dist/src/generated/waterx_referral/referral_table.d.ts +5 -5
- package/dist/src/generated/waterx_referral/referral_table.js +1 -2
- package/dist/src/generated/waterx_staking/waterx_staking.d.ts +19 -19
- package/dist/src/generated/waterx_staking/waterx_staking.js +10 -20
- package/dist/src/generated/waterx_supra_rule/deps/sui/vec_map.d.ts +36 -0
- package/dist/src/generated/waterx_supra_rule/deps/sui/vec_map.js +27 -0
- package/dist/src/generated/waterx_supra_rule/supra_rule.d.ts +158 -0
- package/dist/src/generated/waterx_supra_rule/supra_rule.js +148 -0
- package/dist/src/generated/withdrawal_queue/deps/bucket_v2_framework/float.d.ts +8 -0
- package/dist/src/generated/withdrawal_queue/deps/bucket_v2_framework/float.js +10 -0
- package/dist/src/generated/withdrawal_queue/deps/sui/vec_map.d.ts +36 -0
- package/dist/src/generated/withdrawal_queue/deps/sui/vec_map.js +27 -0
- package/dist/src/generated/withdrawal_queue/withdrawal_queue.d.ts +444 -4
- package/dist/src/generated/withdrawal_queue/withdrawal_queue.js +417 -4
- package/dist/src/generated/wormhole_bridge/wormhole_bridge.d.ts +214 -74
- package/dist/src/generated/wormhole_bridge/wormhole_bridge.js +158 -29
- package/dist/src/index.d.ts +4 -3
- package/dist/src/index.js +3 -2
- package/dist/src/prediction/account.d.ts +96 -0
- package/dist/src/prediction/account.js +230 -0
- package/dist/src/prediction/admin.d.ts +47 -0
- package/dist/src/prediction/admin.js +105 -0
- package/dist/src/prediction/bcs.d.ts +22 -0
- package/dist/src/prediction/bcs.js +240 -0
- package/dist/src/prediction/client.d.ts +75 -0
- package/dist/src/prediction/client.js +164 -0
- package/dist/src/prediction/config.d.ts +60 -0
- package/dist/src/prediction/config.js +75 -0
- package/dist/src/prediction/constants.d.ts +44 -0
- package/dist/src/prediction/constants.js +46 -0
- package/dist/src/prediction/fetch.d.ts +82 -0
- package/dist/src/prediction/fetch.js +270 -0
- package/dist/src/prediction/generated/bucket_v2_framework/account.d.ts +100 -0
- package/dist/src/prediction/generated/bucket_v2_framework/account.js +129 -0
- package/dist/src/prediction/generated/bucket_v2_framework/deps/std/type_name.d.ts +6 -0
- package/dist/src/prediction/generated/bucket_v2_framework/deps/std/type_name.js +19 -0
- package/dist/src/prediction/generated/bucket_v2_framework/deps/sui/balance.d.ts +10 -0
- package/dist/src/prediction/generated/bucket_v2_framework/deps/sui/balance.js +14 -0
- package/dist/src/prediction/generated/bucket_v2_framework/deps/sui/vec_map.d.ts +36 -0
- package/dist/src/prediction/generated/bucket_v2_framework/deps/sui/vec_map.js +27 -0
- package/dist/src/prediction/generated/bucket_v2_framework/deps/sui/vec_set.d.ts +16 -0
- package/dist/src/prediction/generated/bucket_v2_framework/deps/sui/vec_set.js +19 -0
- package/dist/src/prediction/generated/bucket_v2_framework/double.d.ts +382 -0
- package/dist/src/prediction/generated/bucket_v2_framework/double.js +466 -0
- package/dist/src/prediction/generated/bucket_v2_framework/float.d.ts +362 -0
- package/dist/src/prediction/generated/bucket_v2_framework/float.js +440 -0
- package/dist/src/prediction/generated/bucket_v2_framework/liability.d.ts +193 -0
- package/dist/src/prediction/generated/bucket_v2_framework/liability.js +205 -0
- package/dist/src/prediction/generated/bucket_v2_framework/linked_table.d.ts +384 -0
- package/dist/src/prediction/generated/bucket_v2_framework/linked_table.js +382 -0
- package/dist/src/prediction/generated/bucket_v2_framework/sheet.d.ts +344 -0
- package/dist/src/prediction/generated/bucket_v2_framework/sheet.js +338 -0
- package/dist/src/prediction/generated/utils/index.d.ts +30 -0
- package/dist/src/prediction/generated/utils/index.js +160 -0
- package/dist/src/prediction/generated/waterx_account/account.d.ts +1589 -0
- package/dist/src/prediction/generated/waterx_account/account.js +1758 -0
- package/dist/src/prediction/generated/waterx_account/deps/bucket_v2_framework/liability.d.ts +7 -0
- package/dist/src/prediction/generated/waterx_account/deps/bucket_v2_framework/liability.js +13 -0
- package/dist/src/prediction/generated/waterx_account/deps/bucket_v2_framework/sheet.d.ts +7 -0
- package/dist/src/prediction/generated/waterx_account/deps/bucket_v2_framework/sheet.js +16 -0
- package/dist/src/prediction/generated/waterx_account/deps/std/type_name.d.ts +6 -0
- package/dist/src/prediction/generated/waterx_account/deps/std/type_name.js +19 -0
- package/dist/src/prediction/generated/waterx_account/deps/sui/balance.d.ts +10 -0
- package/dist/src/prediction/generated/waterx_account/deps/sui/balance.js +14 -0
- package/dist/src/prediction/generated/waterx_account/deps/sui/object_table.d.ts +12 -0
- package/dist/src/prediction/generated/waterx_account/deps/sui/object_table.js +19 -0
- package/dist/src/prediction/generated/waterx_account/deps/sui/table.d.ts +24 -0
- package/dist/src/prediction/generated/waterx_account/deps/sui/table.js +31 -0
- package/dist/src/prediction/generated/waterx_account/deps/sui/vec_map.d.ts +36 -0
- package/dist/src/prediction/generated/waterx_account/deps/sui/vec_map.js +27 -0
- package/dist/src/prediction/generated/waterx_account/deps/sui/vec_set.d.ts +16 -0
- package/dist/src/prediction/generated/waterx_account/deps/sui/vec_set.js +19 -0
- package/dist/src/prediction/generated/waterx_account/direct_rule.d.ts +75 -0
- package/dist/src/prediction/generated/waterx_account/direct_rule.js +78 -0
- package/dist/src/prediction/generated/waterx_account/events.d.ts +33 -0
- package/dist/src/prediction/generated/waterx_account/events.js +137 -0
- package/dist/src/prediction/generated/waterx_account/version.d.ts +10 -0
- package/dist/src/prediction/generated/waterx_account/version.js +8 -0
- package/dist/src/prediction/generated/waterx_prediction/account_data.d.ts +327 -0
- package/dist/src/prediction/generated/waterx_prediction/account_data.js +405 -0
- package/dist/src/prediction/generated/waterx_prediction/admin.d.ts +5 -0
- package/dist/src/prediction/generated/waterx_prediction/admin.js +9 -0
- package/dist/src/prediction/generated/waterx_prediction/bet_sharing.d.ts +60 -0
- package/dist/src/prediction/generated/waterx_prediction/bet_sharing.js +83 -0
- package/dist/src/prediction/generated/waterx_prediction/deps/bucket_v2_framework/linked_table.d.ts +8 -0
- package/dist/src/prediction/generated/waterx_prediction/deps/bucket_v2_framework/linked_table.js +18 -0
- package/dist/src/prediction/generated/waterx_prediction/deps/sui/balance.d.ts +10 -0
- package/dist/src/prediction/generated/waterx_prediction/deps/sui/balance.js +14 -0
- package/dist/src/prediction/generated/waterx_prediction/deps/sui/table.d.ts +24 -0
- package/dist/src/prediction/generated/waterx_prediction/deps/sui/table.js +31 -0
- package/dist/src/prediction/generated/waterx_prediction/deps/sui/vec_set.d.ts +16 -0
- package/dist/src/prediction/generated/waterx_prediction/deps/sui/vec_set.js +19 -0
- package/dist/src/prediction/generated/waterx_prediction/events.d.ts +22 -0
- package/dist/src/prediction/generated/waterx_prediction/events.js +179 -0
- package/dist/src/prediction/generated/waterx_prediction/global_config.d.ts +116 -0
- package/dist/src/prediction/generated/waterx_prediction/global_config.js +141 -0
- package/dist/src/prediction/generated/waterx_prediction/order.d.ts +200 -0
- package/dist/src/prediction/generated/waterx_prediction/order.js +284 -0
- package/dist/src/prediction/generated/waterx_prediction/outcome.d.ts +58 -0
- package/dist/src/prediction/generated/waterx_prediction/outcome.js +73 -0
- package/dist/src/prediction/generated/waterx_prediction/position.d.ts +160 -0
- package/dist/src/prediction/generated/waterx_prediction/position.js +214 -0
- package/dist/src/prediction/generated/waterx_prediction/version.d.ts +10 -0
- package/dist/src/prediction/generated/waterx_prediction/version.js +8 -0
- package/dist/src/prediction/generated/waterx_prediction/view.d.ts +353 -0
- package/dist/src/prediction/generated/waterx_prediction/view.js +432 -0
- package/dist/src/prediction/generated/waterx_prediction/waterx_prediction.d.ts +1698 -0
- package/dist/src/prediction/generated/waterx_prediction/waterx_prediction.js +1733 -0
- package/dist/src/prediction/gift-link.d.ts +6 -0
- package/dist/src/prediction/gift-link.js +5 -0
- package/dist/src/prediction/gift.d.ts +223 -0
- package/dist/src/prediction/gift.js +451 -0
- package/dist/src/prediction/index.d.ts +29 -0
- package/dist/src/prediction/index.js +21 -0
- package/dist/src/prediction/prediction.d.ts +104 -0
- package/dist/src/prediction/prediction.js +317 -0
- package/dist/src/prediction/tx-builders.d.ts +44 -0
- package/dist/src/prediction/tx-builders.js +52 -0
- package/dist/src/prediction/types.d.ts +93 -0
- package/dist/src/prediction/types.js +1 -0
- package/dist/src/prediction/user/account.d.ts +2 -0
- package/dist/src/prediction/user/account.js +1 -0
- package/dist/src/prediction/user/admin.d.ts +6 -0
- package/dist/src/prediction/user/admin.js +3 -0
- package/dist/src/prediction/user/gift.d.ts +2 -0
- package/dist/src/prediction/user/gift.js +1 -0
- package/dist/src/prediction/user/index.d.ts +5 -0
- package/dist/src/prediction/user/index.js +3 -0
- package/dist/src/prediction/user/keeper.d.ts +2 -0
- package/dist/src/prediction/user/keeper.js +1 -0
- package/dist/src/prediction/user/order.d.ts +2 -0
- package/dist/src/prediction/user/order.js +1 -0
- package/dist/src/prediction/user/position.d.ts +2 -0
- package/dist/src/prediction/user/position.js +1 -0
- package/dist/src/prediction/utils/bcs.d.ts +1 -0
- package/dist/src/prediction/utils/bcs.js +1 -0
- package/dist/src/prediction/utils/index.d.ts +1 -0
- package/dist/src/prediction/utils/index.js +1 -0
- package/dist/src/prediction/utils.d.ts +30 -0
- package/dist/src/prediction/utils.js +177 -0
- package/dist/src/sdk.d.ts +18 -0
- package/dist/src/sdk.js +17 -0
- package/dist/src/tx-builders.d.ts +54 -0
- package/dist/src/tx-builders.js +141 -0
- package/dist/src/unified-client.d.ts +407 -0
- package/dist/src/unified-client.js +123 -0
- package/dist/src/user/account.d.ts +27 -0
- package/dist/src/user/account.js +34 -8
- package/dist/src/user/credit.d.ts +8 -14
- package/dist/src/user/credit.js +9 -23
- package/dist/src/user/custody.d.ts +4 -18
- package/dist/src/user/custody.js +14 -25
- package/dist/src/utils/consolidate-balance.d.ts +37 -0
- package/dist/src/utils/consolidate-balance.js +89 -0
- package/dist/src/utils/math.d.ts +86 -0
- package/dist/src/utils/math.js +100 -0
- package/dist/src/utils/pyth.d.ts +35 -3
- package/dist/src/utils/pyth.js +145 -14
- package/package.json +129 -34
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Browser-safe re-exports of gift URL / KDF crypto helpers (no PredictClient / RPC).
|
|
3
|
+
* Full gift runtime (PTB builders + simulate reads) lives in `./gift.ts`.
|
|
4
|
+
*/
|
|
5
|
+
export { base64UrlNoPadDecode, base64UrlNoPadEncode, buildGiftClaimMessage, deriveGiftKeypair, encodeGiftUrl, generateGiftSeed, parseGiftUrl, signGiftClaim, } from "./gift.ts";
|
|
6
|
+
export type { GiftUrlParts } from "./gift.ts";
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Browser-safe re-exports of gift URL / KDF crypto helpers (no PredictClient / RPC).
|
|
3
|
+
* Full gift runtime (PTB builders + simulate reads) lives in `./gift.ts`.
|
|
4
|
+
*/
|
|
5
|
+
export { base64UrlNoPadDecode, base64UrlNoPadEncode, buildGiftClaimMessage, deriveGiftKeypair, encodeGiftUrl, generateGiftSeed, parseGiftUrl, signGiftClaim, } from "./gift.js";
|
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* waterx_prediction_gift / claimable_link bindings.
|
|
3
|
+
*
|
|
4
|
+
* Three responsibilities:
|
|
5
|
+
*
|
|
6
|
+
* 1. **KDF + signed-message format** — turn a 16-byte URL seed into an
|
|
7
|
+
* Ed25519 keypair (sha256 over a package-prefixed domain) and build
|
|
8
|
+
* the exact 92-byte payload `claim_share` verifies on chain.
|
|
9
|
+
* Every byte here must match `claimable_link.move` — one wrong byte
|
|
10
|
+
* and outstanding URLs break.
|
|
11
|
+
*
|
|
12
|
+
* 2. **URL helpers + offline gift-address derivation** — base64url(no-pad)
|
|
13
|
+
* encode/decode of the seed (URL fragment), and `deriveGiftAddress`
|
|
14
|
+
* which mirrors `derived_object::derive_address` locally so a
|
|
15
|
+
* receiver can compute `gift_id` from the seed without any RPC.
|
|
16
|
+
*
|
|
17
|
+
* 3. **PTB builders + simulate reads** — `createGift` / `claimShare` /
|
|
18
|
+
* `deleteGift` matching the on-chain entrypoints, plus single-RPC
|
|
19
|
+
* `simulateTransaction`-based read helpers for the view fns.
|
|
20
|
+
*/
|
|
21
|
+
import { Ed25519Keypair } from "@mysten/sui/keypairs/ed25519";
|
|
22
|
+
import { Transaction } from "@mysten/sui/transactions";
|
|
23
|
+
import type { PredictClient } from "./client.ts";
|
|
24
|
+
import type { AccountIdentityParams, IdArgument, Selection } from "./types.ts";
|
|
25
|
+
export interface GiftBaseParams {
|
|
26
|
+
/** `waterx_prediction_gift` package id. Defaults to `client.waterxPredictionGiftPackageId()`. */
|
|
27
|
+
giftPackageId?: string;
|
|
28
|
+
/** `ClaimableLinkConfig` object id. Defaults to `client.claimableLinkConfigId()`. */
|
|
29
|
+
claimableLinkConfig?: string;
|
|
30
|
+
/** Collateral / settlement coin type for the position's `Gift<T>`. Defaults to `client.settlementCoinType()`. */
|
|
31
|
+
settlementCoinType?: string;
|
|
32
|
+
}
|
|
33
|
+
export interface GiftReferralParams {
|
|
34
|
+
/** `waterx_referral` package id. Defaults to `client.waterxReferralPackageId()`. */
|
|
35
|
+
referralPackageId?: string;
|
|
36
|
+
/** `ReferralTable` object id. Defaults to `client.referralTableId()`. */
|
|
37
|
+
referralTable?: string;
|
|
38
|
+
}
|
|
39
|
+
export declare function base64UrlNoPadEncode(bytes: Uint8Array): string;
|
|
40
|
+
export declare function base64UrlNoPadDecode(value: string): Uint8Array;
|
|
41
|
+
/** CSPRNG-generated 16-byte URL seed. Uses `globalThis.crypto.getRandomValues`. */
|
|
42
|
+
export declare function generateGiftSeed(): Uint8Array;
|
|
43
|
+
export interface GiftUrlParts {
|
|
44
|
+
/** Optional URL base (`https://waterx.io`). Empty → fragment-only path `/g/#<seed>`. */
|
|
45
|
+
host?: string;
|
|
46
|
+
/** Path prefix before `#<seed>`. Defaults to `/g/`. */
|
|
47
|
+
path?: string;
|
|
48
|
+
}
|
|
49
|
+
/** Build the share URL: `<host><path>#<base64urlnopad(seed)>`. */
|
|
50
|
+
export declare function encodeGiftUrl(seed: Uint8Array, parts?: GiftUrlParts): string;
|
|
51
|
+
/** Parse a share URL or fragment-only string back into the raw seed bytes. */
|
|
52
|
+
export declare function parseGiftUrl(url: string): {
|
|
53
|
+
seed: Uint8Array;
|
|
54
|
+
};
|
|
55
|
+
/**
|
|
56
|
+
* Off-chain KDF: `sha256(KDF_DOMAIN || seed)` → 32-byte Ed25519 secret.
|
|
57
|
+
* Bytes MUST match across SDK versions and downstream integrations or
|
|
58
|
+
* every outstanding URL breaks.
|
|
59
|
+
*/
|
|
60
|
+
export declare function deriveGiftKeypair(seed: Uint8Array): Ed25519Keypair;
|
|
61
|
+
/**
|
|
62
|
+
* Reproduce the bytes `claim_share` verifies:
|
|
63
|
+
* `DOMAIN_CLAIM || bcs(gift_id) || bcs(sender)` = 28 + 32 + 32 = 92 bytes.
|
|
64
|
+
*/
|
|
65
|
+
export declare function buildGiftClaimMessage(giftId: string, sender: string): Uint8Array;
|
|
66
|
+
/**
|
|
67
|
+
* Raw Ed25519 over the claim payload — NOT Sui-intent-prefixed.
|
|
68
|
+
* `claim_share` calls `ed25519::ed25519_verify` directly, so any
|
|
69
|
+
* intent prefix would break verification.
|
|
70
|
+
*/
|
|
71
|
+
export declare function signGiftClaim(giftKeypair: Ed25519Keypair, giftId: string, sender: string): Promise<Uint8Array>;
|
|
72
|
+
/**
|
|
73
|
+
* Compute the `gift_id` that `create_gift` will produce for the given
|
|
74
|
+
* pubkey, offline. No RPC. Mirrors `claimable_link::derive_gift_address`.
|
|
75
|
+
*/
|
|
76
|
+
export declare function deriveGiftAddress(client: PredictClient, pubkey: Uint8Array, params?: GiftBaseParams): string;
|
|
77
|
+
export interface CreateGiftParams extends GiftBaseParams, GiftReferralParams, AccountIdentityParams {
|
|
78
|
+
/** wxa account id (`0x2::object::ID`) that owns the source position. */
|
|
79
|
+
sourceAccountId: IdArgument;
|
|
80
|
+
/** Numeric `position_id` of the position to lock. */
|
|
81
|
+
sourcePositionId: bigint | number | string;
|
|
82
|
+
/** 32-byte gift pubkey (from `deriveGiftKeypair(seed).getPublicKey().toRawBytes()`). */
|
|
83
|
+
pubkey: Uint8Array;
|
|
84
|
+
/** Number of slices, 1..=MAX_SHARES_PER_GIFT. */
|
|
85
|
+
shareCount: bigint | number | string;
|
|
86
|
+
/** Absolute expiry in milliseconds. Must be strictly in the future. */
|
|
87
|
+
expiresAtMs: bigint | number | string;
|
|
88
|
+
/** Optional referral code applied to every claimer (idempotent). */
|
|
89
|
+
referralCode?: string | null;
|
|
90
|
+
/** Override `MarketRegistry<T>` id. Defaults to `client.marketRegistry()`. */
|
|
91
|
+
marketRegistry?: string;
|
|
92
|
+
/** Override `AccountRegistry` id. Defaults to `client.accountRegistry()`. */
|
|
93
|
+
accountRegistry?: string;
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Lock one position behind `pubkey` and share it as a gift. Adds a
|
|
97
|
+
* single `claimable_link::create_gift<T>` call to `tx` using the
|
|
98
|
+
* caller's `bucket_framework::account::request` as the source-owner
|
|
99
|
+
* authority. The transaction sender (`ctx.sender()`) must be the owner
|
|
100
|
+
* of `sourceAccountId`.
|
|
101
|
+
*/
|
|
102
|
+
export declare function createGift(client: PredictClient, tx: Transaction, params: CreateGiftParams): Transaction;
|
|
103
|
+
export interface ClaimShareParams extends GiftBaseParams, GiftReferralParams {
|
|
104
|
+
/** Shared `Gift<T>` object id. Derive locally via `deriveGiftAddress`. */
|
|
105
|
+
giftId: string;
|
|
106
|
+
/** Raw 64-byte Ed25519 signature over `buildGiftClaimMessage(giftId, sender)`. */
|
|
107
|
+
sig: Uint8Array;
|
|
108
|
+
/**
|
|
109
|
+
* Recipient wxa account id, or `null`/`undefined` to land in the
|
|
110
|
+
* claimer's main wxa (auto-created with alias `"main"` if the
|
|
111
|
+
* claimer has none yet).
|
|
112
|
+
*/
|
|
113
|
+
recipientAccountId?: IdArgument | null;
|
|
114
|
+
/** prediction `GlobalConfig` id. Defaults to `client.globalConfigId()`. */
|
|
115
|
+
globalConfig?: string;
|
|
116
|
+
/** prediction `MarketRegistry<T>` id. Defaults to `client.marketRegistry()`. */
|
|
117
|
+
marketRegistry?: string;
|
|
118
|
+
/** `waterx_account::AccountRegistry` id. Defaults to `client.accountRegistry()`. */
|
|
119
|
+
accountRegistry?: string;
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Claim one slice of a gift. The signature must be raw Ed25519 (NOT
|
|
123
|
+
* Sui-intent-prefixed) over `DOMAIN_CLAIM || gift_id || sender`.
|
|
124
|
+
* Pre-flight: fetch the gift and check `claimed_count < share_count`,
|
|
125
|
+
* `now < expires_at_ms`, and `!claimed_addresses.contains(sender)` to
|
|
126
|
+
* surface "already claimed" client-side instead of paying gas to abort.
|
|
127
|
+
*/
|
|
128
|
+
export declare function claimShare(client: PredictClient, tx: Transaction, params: ClaimShareParams): Transaction;
|
|
129
|
+
export interface DeleteGiftParams extends GiftBaseParams, AccountIdentityParams {
|
|
130
|
+
/** Shared `Gift<T>` object id to consume. */
|
|
131
|
+
giftId: string;
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Creator-driven hard delete. Consumes the `Gift<T>` by value and
|
|
135
|
+
* removes it from `config.creator_gifts[creator]`. The source position
|
|
136
|
+
* stays on the creator's wxa; nothing to refund. Skips the paused gate
|
|
137
|
+
* — cancel must work even when the package is paused.
|
|
138
|
+
*/
|
|
139
|
+
export declare function deleteGift(client: PredictClient, tx: Transaction, params: DeleteGiftParams): Transaction;
|
|
140
|
+
export interface GiftView {
|
|
141
|
+
giftId: string;
|
|
142
|
+
creator: string;
|
|
143
|
+
creatorAccountId: string;
|
|
144
|
+
sourcePositionId: bigint;
|
|
145
|
+
marketId: Uint8Array;
|
|
146
|
+
marketIdHex: string;
|
|
147
|
+
selection: Selection;
|
|
148
|
+
totalSpend: bigint;
|
|
149
|
+
spendPerShare: bigint;
|
|
150
|
+
lockedOddsCents: bigint;
|
|
151
|
+
pubkey: Uint8Array;
|
|
152
|
+
shareCount: bigint;
|
|
153
|
+
claimedCount: bigint;
|
|
154
|
+
claimedAddresses: string[];
|
|
155
|
+
baseShareAmount: bigint;
|
|
156
|
+
extraShareLinks: bigint;
|
|
157
|
+
totalShares: bigint;
|
|
158
|
+
remainingShares: bigint;
|
|
159
|
+
referralCode: string | null;
|
|
160
|
+
createdAtMs: bigint;
|
|
161
|
+
expiresAtMs: bigint;
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* Fetch a single gift's full view in one RPC by batching every getter
|
|
165
|
+
* into one simulated PTB. Decodes each `commandResults[i].returnValues[0]`
|
|
166
|
+
* into the corresponding TypeScript field.
|
|
167
|
+
*/
|
|
168
|
+
export declare function getGift(client: PredictClient, params: GiftBaseParams & {
|
|
169
|
+
giftId: string;
|
|
170
|
+
}): Promise<GiftView>;
|
|
171
|
+
/** Live gift IDs for a creator. Order isn't preserved — sort by `createdAtMs`. */
|
|
172
|
+
export declare function getCreatorGiftIds(client: PredictClient, params: GiftBaseParams & {
|
|
173
|
+
creator: string;
|
|
174
|
+
}): Promise<string[]>;
|
|
175
|
+
export declare function getCreatorGiftCount(client: PredictClient, params: GiftBaseParams & {
|
|
176
|
+
creator: string;
|
|
177
|
+
}): Promise<bigint>;
|
|
178
|
+
/**
|
|
179
|
+
* Global controller delegate address. Same value for every creator,
|
|
180
|
+
* stable for the package's lifetime. Surface on FE so creators can
|
|
181
|
+
* verify the right delegate is registered on their wxa.
|
|
182
|
+
*/
|
|
183
|
+
export declare function getGiftControllerAddress(client: PredictClient, params?: GiftBaseParams): Promise<string>;
|
|
184
|
+
export declare function getGiftConfigPaused(client: PredictClient, params?: GiftBaseParams): Promise<boolean>;
|
|
185
|
+
export declare function getGiftHasClaimed(client: PredictClient, params: GiftBaseParams & {
|
|
186
|
+
giftId: string;
|
|
187
|
+
addr: string;
|
|
188
|
+
}): Promise<boolean>;
|
|
189
|
+
export interface BuildCreateGiftFlowResult {
|
|
190
|
+
tx: Transaction;
|
|
191
|
+
/** Raw 16-byte seed. Encode into the share URL with `encodeGiftUrl`. */
|
|
192
|
+
seed: Uint8Array;
|
|
193
|
+
/** Predicted gift ID (computed locally from `(config, pubkey)`). */
|
|
194
|
+
giftId: string;
|
|
195
|
+
/** 32-byte gift pubkey, in case the caller wants to log/store it. */
|
|
196
|
+
pubkey: Uint8Array;
|
|
197
|
+
}
|
|
198
|
+
/**
|
|
199
|
+
* One-shot: generate a fresh seed, derive the gift keypair + pubkey,
|
|
200
|
+
* compute the predicted `gift_id`, and add the `create_gift` call to
|
|
201
|
+
* `tx`. The caller signs + executes `tx` and then renders the URL via
|
|
202
|
+
* `encodeGiftUrl(seed, …)`.
|
|
203
|
+
*/
|
|
204
|
+
export declare function buildCreateGiftFlow(client: PredictClient, tx: Transaction, params: Omit<CreateGiftParams, "pubkey">): BuildCreateGiftFlowResult;
|
|
205
|
+
export interface BuildClaimShareFlowParams extends Omit<ClaimShareParams, "sig" | "giftId"> {
|
|
206
|
+
/** The 16-byte seed parsed from the share URL fragment. */
|
|
207
|
+
seed: Uint8Array;
|
|
208
|
+
/** The transaction sender (becomes `ctx.sender()`). Bound into the sig. */
|
|
209
|
+
sender: string;
|
|
210
|
+
/** Optional override — defaults to `deriveGiftAddress(client, pubkey)`. */
|
|
211
|
+
giftId?: string;
|
|
212
|
+
}
|
|
213
|
+
export interface BuildClaimShareFlowResult {
|
|
214
|
+
tx: Transaction;
|
|
215
|
+
giftId: string;
|
|
216
|
+
sig: Uint8Array;
|
|
217
|
+
}
|
|
218
|
+
/**
|
|
219
|
+
* One-shot: derive the gift keypair from `seed`, compute `gift_id`,
|
|
220
|
+
* sign the claim payload bound to `sender`, and add the `claim_share`
|
|
221
|
+
* call to `tx`. Caller signs + executes `tx` with `sender`'s keypair.
|
|
222
|
+
*/
|
|
223
|
+
export declare function buildClaimShareFlow(client: PredictClient, tx: Transaction, params: BuildClaimShareFlowParams): Promise<BuildClaimShareFlowResult>;
|
|
@@ -0,0 +1,451 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* waterx_prediction_gift / claimable_link bindings.
|
|
3
|
+
*
|
|
4
|
+
* Three responsibilities:
|
|
5
|
+
*
|
|
6
|
+
* 1. **KDF + signed-message format** — turn a 16-byte URL seed into an
|
|
7
|
+
* Ed25519 keypair (sha256 over a package-prefixed domain) and build
|
|
8
|
+
* the exact 92-byte payload `claim_share` verifies on chain.
|
|
9
|
+
* Every byte here must match `claimable_link.move` — one wrong byte
|
|
10
|
+
* and outstanding URLs break.
|
|
11
|
+
*
|
|
12
|
+
* 2. **URL helpers + offline gift-address derivation** — base64url(no-pad)
|
|
13
|
+
* encode/decode of the seed (URL fragment), and `deriveGiftAddress`
|
|
14
|
+
* which mirrors `derived_object::derive_address` locally so a
|
|
15
|
+
* receiver can compute `gift_id` from the seed without any RPC.
|
|
16
|
+
*
|
|
17
|
+
* 3. **PTB builders + simulate reads** — `createGift` / `claimShare` /
|
|
18
|
+
* `deleteGift` matching the on-chain entrypoints, plus single-RPC
|
|
19
|
+
* `simulateTransaction`-based read helpers for the view fns.
|
|
20
|
+
*/
|
|
21
|
+
import { bcs } from "@mysten/sui/bcs";
|
|
22
|
+
import { Ed25519Keypair } from "@mysten/sui/keypairs/ed25519";
|
|
23
|
+
import { Transaction } from "@mysten/sui/transactions";
|
|
24
|
+
import { deriveObjectID, fromBase64, toBase64 } from "@mysten/sui/utils";
|
|
25
|
+
import { sha256 } from "@noble/hashes/sha2.js";
|
|
26
|
+
import { SelectionBcs } from "./bcs.js";
|
|
27
|
+
import { GIFT_DOMAIN_CLAIM, GIFT_KDF_DOMAIN, GIFT_PUBKEY_LEN, GIFT_SIG_LEN, GIFT_URL_SEED_BYTES, } from "./constants.js";
|
|
28
|
+
import { extractReturnBytes } from "./fetch.js";
|
|
29
|
+
import { clockArg, createAccountRequest, idArg, resolveAccountRegistry, resolveGlobalConfig, resolveMarketRegistry, resolveSettlementCoinType, toBigInt, } from "./utils.js";
|
|
30
|
+
function resolveGiftPackageId(client, override) {
|
|
31
|
+
return override === undefined || override === ""
|
|
32
|
+
? client.waterxPredictionGiftPackageId()
|
|
33
|
+
: override;
|
|
34
|
+
}
|
|
35
|
+
function resolveClaimableLinkConfig(client, override) {
|
|
36
|
+
return override === undefined || override === "" ? client.claimableLinkConfigId() : override;
|
|
37
|
+
}
|
|
38
|
+
function resolveReferralTable(client, override) {
|
|
39
|
+
return override === undefined || override === "" ? client.referralTableId() : override;
|
|
40
|
+
}
|
|
41
|
+
// ---------------------------------------------------------------------
|
|
42
|
+
// URL / base64url(no-pad) helpers
|
|
43
|
+
//
|
|
44
|
+
// Standard base64 maps to base64url by replacing +/= → -_ and dropping
|
|
45
|
+
// padding. Tiny enough to avoid pulling @scure/base.
|
|
46
|
+
// ---------------------------------------------------------------------
|
|
47
|
+
export function base64UrlNoPadEncode(bytes) {
|
|
48
|
+
return toBase64(bytes).replaceAll("+", "-").replaceAll("/", "_").replace(/=+$/, "");
|
|
49
|
+
}
|
|
50
|
+
export function base64UrlNoPadDecode(value) {
|
|
51
|
+
let b64 = value.replaceAll("-", "+").replaceAll("_", "/");
|
|
52
|
+
while (b64.length % 4 !== 0)
|
|
53
|
+
b64 += "=";
|
|
54
|
+
return fromBase64(b64);
|
|
55
|
+
}
|
|
56
|
+
/** CSPRNG-generated 16-byte URL seed. Uses `globalThis.crypto.getRandomValues`. */
|
|
57
|
+
export function generateGiftSeed() {
|
|
58
|
+
const seed = new Uint8Array(GIFT_URL_SEED_BYTES);
|
|
59
|
+
if (typeof globalThis.crypto?.getRandomValues !== "function") {
|
|
60
|
+
throw new Error("generateGiftSeed: globalThis.crypto.getRandomValues is unavailable; use Node >= 19 or a polyfill");
|
|
61
|
+
}
|
|
62
|
+
globalThis.crypto.getRandomValues(seed);
|
|
63
|
+
return seed;
|
|
64
|
+
}
|
|
65
|
+
/** Build the share URL: `<host><path>#<base64urlnopad(seed)>`. */
|
|
66
|
+
export function encodeGiftUrl(seed, parts = {}) {
|
|
67
|
+
assertSeedLength(seed);
|
|
68
|
+
const host = parts.host ?? "";
|
|
69
|
+
const path = parts.path ?? "/g/";
|
|
70
|
+
return `${host}${path}#${base64UrlNoPadEncode(seed)}`;
|
|
71
|
+
}
|
|
72
|
+
/** Parse a share URL or fragment-only string back into the raw seed bytes. */
|
|
73
|
+
export function parseGiftUrl(url) {
|
|
74
|
+
const hashIdx = url.indexOf("#");
|
|
75
|
+
if (hashIdx === -1) {
|
|
76
|
+
throw new Error("parseGiftUrl: no '#' fragment in URL");
|
|
77
|
+
}
|
|
78
|
+
const fragment = url.slice(hashIdx + 1);
|
|
79
|
+
if (fragment === "")
|
|
80
|
+
throw new Error("parseGiftUrl: empty fragment");
|
|
81
|
+
const seed = base64UrlNoPadDecode(fragment);
|
|
82
|
+
assertSeedLength(seed);
|
|
83
|
+
return { seed };
|
|
84
|
+
}
|
|
85
|
+
function assertSeedLength(seed) {
|
|
86
|
+
if (seed.length !== GIFT_URL_SEED_BYTES) {
|
|
87
|
+
throw new Error(`Gift URL seed must be ${GIFT_URL_SEED_BYTES} bytes, got ${seed.length}`);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
// ---------------------------------------------------------------------
|
|
91
|
+
// KDF + signed-message
|
|
92
|
+
// ---------------------------------------------------------------------
|
|
93
|
+
function concatBytes(...parts) {
|
|
94
|
+
let total = 0;
|
|
95
|
+
for (const p of parts)
|
|
96
|
+
total += p.length;
|
|
97
|
+
const out = new Uint8Array(total);
|
|
98
|
+
let offset = 0;
|
|
99
|
+
for (const p of parts) {
|
|
100
|
+
out.set(p, offset);
|
|
101
|
+
offset += p.length;
|
|
102
|
+
}
|
|
103
|
+
return out;
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Off-chain KDF: `sha256(KDF_DOMAIN || seed)` → 32-byte Ed25519 secret.
|
|
107
|
+
* Bytes MUST match across SDK versions and downstream integrations or
|
|
108
|
+
* every outstanding URL breaks.
|
|
109
|
+
*/
|
|
110
|
+
export function deriveGiftKeypair(seed) {
|
|
111
|
+
assertSeedLength(seed);
|
|
112
|
+
const secret = sha256(concatBytes(GIFT_KDF_DOMAIN, seed));
|
|
113
|
+
return Ed25519Keypair.fromSecretKey(secret);
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Reproduce the bytes `claim_share` verifies:
|
|
117
|
+
* `DOMAIN_CLAIM || bcs(gift_id) || bcs(sender)` = 28 + 32 + 32 = 92 bytes.
|
|
118
|
+
*/
|
|
119
|
+
export function buildGiftClaimMessage(giftId, sender) {
|
|
120
|
+
return concatBytes(GIFT_DOMAIN_CLAIM, bcs.Address.serialize(giftId).toBytes(), bcs.Address.serialize(sender).toBytes());
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Raw Ed25519 over the claim payload — NOT Sui-intent-prefixed.
|
|
124
|
+
* `claim_share` calls `ed25519::ed25519_verify` directly, so any
|
|
125
|
+
* intent prefix would break verification.
|
|
126
|
+
*/
|
|
127
|
+
export async function signGiftClaim(giftKeypair, giftId, sender) {
|
|
128
|
+
const sig = await giftKeypair.sign(buildGiftClaimMessage(giftId, sender));
|
|
129
|
+
if (sig.length !== GIFT_SIG_LEN) {
|
|
130
|
+
throw new Error(`Gift signature must be ${GIFT_SIG_LEN} bytes, got ${sig.length}`);
|
|
131
|
+
}
|
|
132
|
+
return sig;
|
|
133
|
+
}
|
|
134
|
+
// ---------------------------------------------------------------------
|
|
135
|
+
// Offline gift-address derivation
|
|
136
|
+
//
|
|
137
|
+
// Mirrors `derived_object::derive_address(parent_id, GiftKey { pubkey })`.
|
|
138
|
+
// `deriveObjectID` from @mysten/sui/utils wraps the key in
|
|
139
|
+
// `DerivedObjectKey<K>` and hashes parent_id || type_tag || bcs(key)
|
|
140
|
+
// with blake2b-256, which matches the on-chain formula.
|
|
141
|
+
// ---------------------------------------------------------------------
|
|
142
|
+
const GiftKeyBcs = bcs.struct("GiftKey", {
|
|
143
|
+
pubkey: bcs.vector(bcs.u8()),
|
|
144
|
+
});
|
|
145
|
+
/**
|
|
146
|
+
* Compute the `gift_id` that `create_gift` will produce for the given
|
|
147
|
+
* pubkey, offline. No RPC. Mirrors `claimable_link::derive_gift_address`.
|
|
148
|
+
*/
|
|
149
|
+
export function deriveGiftAddress(client, pubkey, params = {}) {
|
|
150
|
+
if (pubkey.length !== GIFT_PUBKEY_LEN) {
|
|
151
|
+
throw new Error(`Gift pubkey must be ${GIFT_PUBKEY_LEN} bytes, got ${pubkey.length}`);
|
|
152
|
+
}
|
|
153
|
+
const giftPkg = resolveGiftPackageId(client, params.giftPackageId);
|
|
154
|
+
const configId = resolveClaimableLinkConfig(client, params.claimableLinkConfig);
|
|
155
|
+
const keyBytes = GiftKeyBcs.serialize({ pubkey: Array.from(pubkey) }).toBytes();
|
|
156
|
+
return deriveObjectID(configId, `${giftPkg}::claimable_link::GiftKey`, keyBytes);
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Lock one position behind `pubkey` and share it as a gift. Adds a
|
|
160
|
+
* single `claimable_link::create_gift<T>` call to `tx` using the
|
|
161
|
+
* caller's `bucket_framework::account::request` as the source-owner
|
|
162
|
+
* authority. The transaction sender (`ctx.sender()`) must be the owner
|
|
163
|
+
* of `sourceAccountId`.
|
|
164
|
+
*/
|
|
165
|
+
export function createGift(client, tx, params) {
|
|
166
|
+
if (params.pubkey.length !== GIFT_PUBKEY_LEN) {
|
|
167
|
+
throw new Error(`createGift: pubkey must be ${GIFT_PUBKEY_LEN} bytes, got ${params.pubkey.length}`);
|
|
168
|
+
}
|
|
169
|
+
const giftPkg = resolveGiftPackageId(client, params.giftPackageId);
|
|
170
|
+
const coinType = resolveSettlementCoinType(client, params.settlementCoinType);
|
|
171
|
+
const sourceOwnerRequest = createAccountRequest(client, tx, params);
|
|
172
|
+
tx.moveCall({
|
|
173
|
+
target: `${giftPkg}::claimable_link::create_gift`,
|
|
174
|
+
typeArguments: [coinType],
|
|
175
|
+
arguments: [
|
|
176
|
+
tx.object(resolveClaimableLinkConfig(client, params.claimableLinkConfig)),
|
|
177
|
+
tx.object(resolveMarketRegistry(client, params.marketRegistry)),
|
|
178
|
+
tx.object(resolveAccountRegistry(client, params.accountRegistry)),
|
|
179
|
+
tx.object(resolveReferralTable(client, params.referralTable)),
|
|
180
|
+
sourceOwnerRequest,
|
|
181
|
+
idArg(tx, params.sourceAccountId),
|
|
182
|
+
tx.pure.u64(toBigInt(params.sourcePositionId)),
|
|
183
|
+
tx.pure.vector("u8", Array.from(params.pubkey)),
|
|
184
|
+
tx.pure.u64(toBigInt(params.shareCount)),
|
|
185
|
+
tx.pure.u64(toBigInt(params.expiresAtMs)),
|
|
186
|
+
tx.pure.option("string", params.referralCode ?? null),
|
|
187
|
+
clockArg(tx),
|
|
188
|
+
],
|
|
189
|
+
});
|
|
190
|
+
return tx;
|
|
191
|
+
}
|
|
192
|
+
/**
|
|
193
|
+
* Claim one slice of a gift. The signature must be raw Ed25519 (NOT
|
|
194
|
+
* Sui-intent-prefixed) over `DOMAIN_CLAIM || gift_id || sender`.
|
|
195
|
+
* Pre-flight: fetch the gift and check `claimed_count < share_count`,
|
|
196
|
+
* `now < expires_at_ms`, and `!claimed_addresses.contains(sender)` to
|
|
197
|
+
* surface "already claimed" client-side instead of paying gas to abort.
|
|
198
|
+
*/
|
|
199
|
+
export function claimShare(client, tx, params) {
|
|
200
|
+
if (params.sig.length !== GIFT_SIG_LEN) {
|
|
201
|
+
throw new Error(`claimShare: sig must be ${GIFT_SIG_LEN} bytes, got ${params.sig.length}`);
|
|
202
|
+
}
|
|
203
|
+
const giftPkg = resolveGiftPackageId(client, params.giftPackageId);
|
|
204
|
+
const coinType = resolveSettlementCoinType(client, params.settlementCoinType);
|
|
205
|
+
// recipient_account_id is `Option<ID>` — tx.pure.option only accepts a
|
|
206
|
+
// string literal id, so a TransactionArgument here would need a
|
|
207
|
+
// different code path (build the Option via Move calls). Bail loudly.
|
|
208
|
+
if (params.recipientAccountId !== undefined &&
|
|
209
|
+
params.recipientAccountId !== null &&
|
|
210
|
+
typeof params.recipientAccountId !== "string") {
|
|
211
|
+
throw new Error("claimShare: recipientAccountId must be a string id or null/undefined");
|
|
212
|
+
}
|
|
213
|
+
tx.moveCall({
|
|
214
|
+
target: `${giftPkg}::claimable_link::claim_share`,
|
|
215
|
+
typeArguments: [coinType],
|
|
216
|
+
arguments: [
|
|
217
|
+
tx.object(resolveClaimableLinkConfig(client, params.claimableLinkConfig)),
|
|
218
|
+
tx.object(params.giftId),
|
|
219
|
+
tx.object(resolveGlobalConfig(client, params.globalConfig)),
|
|
220
|
+
tx.object(resolveMarketRegistry(client, params.marketRegistry)),
|
|
221
|
+
tx.object(resolveAccountRegistry(client, params.accountRegistry)),
|
|
222
|
+
tx.object(resolveReferralTable(client, params.referralTable)),
|
|
223
|
+
tx.pure.option("id", params.recipientAccountId ?? null),
|
|
224
|
+
tx.pure.vector("u8", Array.from(params.sig)),
|
|
225
|
+
clockArg(tx),
|
|
226
|
+
],
|
|
227
|
+
});
|
|
228
|
+
return tx;
|
|
229
|
+
}
|
|
230
|
+
/**
|
|
231
|
+
* Creator-driven hard delete. Consumes the `Gift<T>` by value and
|
|
232
|
+
* removes it from `config.creator_gifts[creator]`. The source position
|
|
233
|
+
* stays on the creator's wxa; nothing to refund. Skips the paused gate
|
|
234
|
+
* — cancel must work even when the package is paused.
|
|
235
|
+
*/
|
|
236
|
+
export function deleteGift(client, tx, params) {
|
|
237
|
+
const giftPkg = resolveGiftPackageId(client, params.giftPackageId);
|
|
238
|
+
const coinType = resolveSettlementCoinType(client, params.settlementCoinType);
|
|
239
|
+
const creatorRequest = createAccountRequest(client, tx, params);
|
|
240
|
+
tx.moveCall({
|
|
241
|
+
target: `${giftPkg}::claimable_link::delete_gift`,
|
|
242
|
+
typeArguments: [coinType],
|
|
243
|
+
arguments: [
|
|
244
|
+
tx.object(resolveClaimableLinkConfig(client, params.claimableLinkConfig)),
|
|
245
|
+
tx.object(params.giftId),
|
|
246
|
+
creatorRequest,
|
|
247
|
+
clockArg(tx),
|
|
248
|
+
],
|
|
249
|
+
});
|
|
250
|
+
return tx;
|
|
251
|
+
}
|
|
252
|
+
/**
|
|
253
|
+
* Fetch a single gift's full view in one RPC by batching every getter
|
|
254
|
+
* into one simulated PTB. Decodes each `commandResults[i].returnValues[0]`
|
|
255
|
+
* into the corresponding TypeScript field.
|
|
256
|
+
*/
|
|
257
|
+
export async function getGift(client, params) {
|
|
258
|
+
const giftPkg = resolveGiftPackageId(client, params.giftPackageId);
|
|
259
|
+
const coinType = resolveSettlementCoinType(client, params.settlementCoinType);
|
|
260
|
+
const tx = new Transaction();
|
|
261
|
+
const giftArg = tx.object(params.giftId);
|
|
262
|
+
// Ordering is load-bearing: result decoders below index by command position.
|
|
263
|
+
const callGetter = (name) => {
|
|
264
|
+
tx.moveCall({
|
|
265
|
+
target: `${giftPkg}::claimable_link::${name}`,
|
|
266
|
+
typeArguments: [coinType],
|
|
267
|
+
arguments: [giftArg],
|
|
268
|
+
});
|
|
269
|
+
};
|
|
270
|
+
const getterOrder = [
|
|
271
|
+
"gift_id",
|
|
272
|
+
"creator",
|
|
273
|
+
"creator_account_id",
|
|
274
|
+
"source_position_id",
|
|
275
|
+
"market_id",
|
|
276
|
+
"selection",
|
|
277
|
+
"total_spend",
|
|
278
|
+
"spend_per_share",
|
|
279
|
+
"locked_odds_cents",
|
|
280
|
+
"pubkey",
|
|
281
|
+
"share_count",
|
|
282
|
+
"claimed_count",
|
|
283
|
+
"claimed_addresses",
|
|
284
|
+
"base_share_amount",
|
|
285
|
+
"extra_share_links",
|
|
286
|
+
"total_shares",
|
|
287
|
+
"remaining_shares",
|
|
288
|
+
"referral_code",
|
|
289
|
+
"created_at_ms",
|
|
290
|
+
"expires_at_ms",
|
|
291
|
+
];
|
|
292
|
+
for (const g of getterOrder)
|
|
293
|
+
callGetter(g);
|
|
294
|
+
const result = await client.simulate(tx);
|
|
295
|
+
let i = 0;
|
|
296
|
+
const id = () => bcs.Address.parse(extractReturnBytes(result, i++));
|
|
297
|
+
const u64 = () => BigInt(bcs.u64().parse(extractReturnBytes(result, i++)));
|
|
298
|
+
const bytes = () => new Uint8Array(bcs.vector(bcs.u8()).parse(extractReturnBytes(result, i++)));
|
|
299
|
+
const sel = () => {
|
|
300
|
+
const parsed = SelectionBcs.parse(extractReturnBytes(result, i++));
|
|
301
|
+
const variant = parsed?.$kind ?? parsed; // bcs.enum returns { $kind } in v2
|
|
302
|
+
if (variant === "Yes" || variant === "YES")
|
|
303
|
+
return "YES";
|
|
304
|
+
if (variant === "No" || variant === "NO")
|
|
305
|
+
return "NO";
|
|
306
|
+
throw new Error(`Unrecognized Selection variant: ${JSON.stringify(parsed)}`);
|
|
307
|
+
};
|
|
308
|
+
const addrs = () => bcs.vector(bcs.Address).parse(extractReturnBytes(result, i++));
|
|
309
|
+
const optString = () => bcs.option(bcs.string()).parse(extractReturnBytes(result, i++));
|
|
310
|
+
const giftId = id();
|
|
311
|
+
const creator = id();
|
|
312
|
+
const creatorAccountId = id();
|
|
313
|
+
const sourcePositionId = u64();
|
|
314
|
+
const marketIdBytes = bytes();
|
|
315
|
+
const selection = sel();
|
|
316
|
+
const totalSpend = u64();
|
|
317
|
+
const spendPerShare = u64();
|
|
318
|
+
const lockedOddsCents = u64();
|
|
319
|
+
const pubkey = bytes();
|
|
320
|
+
const shareCount = u64();
|
|
321
|
+
const claimedCount = u64();
|
|
322
|
+
const claimedAddresses = addrs();
|
|
323
|
+
const baseShareAmount = u64();
|
|
324
|
+
const extraShareLinks = u64();
|
|
325
|
+
const totalShares = u64();
|
|
326
|
+
const remainingShares = u64();
|
|
327
|
+
const referralCode = optString();
|
|
328
|
+
const createdAtMs = u64();
|
|
329
|
+
const expiresAtMs = u64();
|
|
330
|
+
return {
|
|
331
|
+
giftId,
|
|
332
|
+
creator,
|
|
333
|
+
creatorAccountId,
|
|
334
|
+
sourcePositionId,
|
|
335
|
+
marketId: marketIdBytes,
|
|
336
|
+
marketIdHex: bytesToHexLocal(marketIdBytes),
|
|
337
|
+
selection,
|
|
338
|
+
totalSpend,
|
|
339
|
+
spendPerShare,
|
|
340
|
+
lockedOddsCents,
|
|
341
|
+
pubkey,
|
|
342
|
+
shareCount,
|
|
343
|
+
claimedCount,
|
|
344
|
+
claimedAddresses,
|
|
345
|
+
baseShareAmount,
|
|
346
|
+
extraShareLinks,
|
|
347
|
+
totalShares,
|
|
348
|
+
remainingShares,
|
|
349
|
+
referralCode: referralCode ?? null,
|
|
350
|
+
createdAtMs,
|
|
351
|
+
expiresAtMs,
|
|
352
|
+
};
|
|
353
|
+
}
|
|
354
|
+
// Local copy of the hex helper to avoid a circular import via utils.ts.
|
|
355
|
+
function bytesToHexLocal(bytes) {
|
|
356
|
+
let out = "0x";
|
|
357
|
+
for (const b of bytes)
|
|
358
|
+
out += b.toString(16).padStart(2, "0");
|
|
359
|
+
return out;
|
|
360
|
+
}
|
|
361
|
+
/** Live gift IDs for a creator. Order isn't preserved — sort by `createdAtMs`. */
|
|
362
|
+
export async function getCreatorGiftIds(client, params) {
|
|
363
|
+
const giftPkg = resolveGiftPackageId(client, params.giftPackageId);
|
|
364
|
+
const tx = new Transaction();
|
|
365
|
+
tx.moveCall({
|
|
366
|
+
target: `${giftPkg}::claimable_link::creator_gift_ids`,
|
|
367
|
+
arguments: [
|
|
368
|
+
tx.object(resolveClaimableLinkConfig(client, params.claimableLinkConfig)),
|
|
369
|
+
tx.pure.address(params.creator),
|
|
370
|
+
],
|
|
371
|
+
});
|
|
372
|
+
const result = await client.simulate(tx);
|
|
373
|
+
return bcs.vector(bcs.Address).parse(extractReturnBytes(result));
|
|
374
|
+
}
|
|
375
|
+
export async function getCreatorGiftCount(client, params) {
|
|
376
|
+
const giftPkg = resolveGiftPackageId(client, params.giftPackageId);
|
|
377
|
+
const tx = new Transaction();
|
|
378
|
+
tx.moveCall({
|
|
379
|
+
target: `${giftPkg}::claimable_link::creator_gift_count`,
|
|
380
|
+
arguments: [
|
|
381
|
+
tx.object(resolveClaimableLinkConfig(client, params.claimableLinkConfig)),
|
|
382
|
+
tx.pure.address(params.creator),
|
|
383
|
+
],
|
|
384
|
+
});
|
|
385
|
+
const result = await client.simulate(tx);
|
|
386
|
+
return BigInt(bcs.u64().parse(extractReturnBytes(result)));
|
|
387
|
+
}
|
|
388
|
+
/**
|
|
389
|
+
* Global controller delegate address. Same value for every creator,
|
|
390
|
+
* stable for the package's lifetime. Surface on FE so creators can
|
|
391
|
+
* verify the right delegate is registered on their wxa.
|
|
392
|
+
*/
|
|
393
|
+
export async function getGiftControllerAddress(client, params = {}) {
|
|
394
|
+
const giftPkg = resolveGiftPackageId(client, params.giftPackageId);
|
|
395
|
+
const tx = new Transaction();
|
|
396
|
+
tx.moveCall({
|
|
397
|
+
target: `${giftPkg}::claimable_link::controller_address`,
|
|
398
|
+
arguments: [tx.object(resolveClaimableLinkConfig(client, params.claimableLinkConfig))],
|
|
399
|
+
});
|
|
400
|
+
const result = await client.simulate(tx);
|
|
401
|
+
return bcs.Address.parse(extractReturnBytes(result));
|
|
402
|
+
}
|
|
403
|
+
export async function getGiftConfigPaused(client, params = {}) {
|
|
404
|
+
const giftPkg = resolveGiftPackageId(client, params.giftPackageId);
|
|
405
|
+
const tx = new Transaction();
|
|
406
|
+
tx.moveCall({
|
|
407
|
+
target: `${giftPkg}::claimable_link::is_paused`,
|
|
408
|
+
arguments: [tx.object(resolveClaimableLinkConfig(client, params.claimableLinkConfig))],
|
|
409
|
+
});
|
|
410
|
+
const result = await client.simulate(tx);
|
|
411
|
+
return bcs.bool().parse(extractReturnBytes(result));
|
|
412
|
+
}
|
|
413
|
+
export async function getGiftHasClaimed(client, params) {
|
|
414
|
+
const giftPkg = resolveGiftPackageId(client, params.giftPackageId);
|
|
415
|
+
const coinType = resolveSettlementCoinType(client, params.settlementCoinType);
|
|
416
|
+
const tx = new Transaction();
|
|
417
|
+
tx.moveCall({
|
|
418
|
+
target: `${giftPkg}::claimable_link::has_claimed`,
|
|
419
|
+
typeArguments: [coinType],
|
|
420
|
+
arguments: [tx.object(params.giftId), tx.pure.address(params.addr)],
|
|
421
|
+
});
|
|
422
|
+
const result = await client.simulate(tx);
|
|
423
|
+
return bcs.bool().parse(extractReturnBytes(result));
|
|
424
|
+
}
|
|
425
|
+
/**
|
|
426
|
+
* One-shot: generate a fresh seed, derive the gift keypair + pubkey,
|
|
427
|
+
* compute the predicted `gift_id`, and add the `create_gift` call to
|
|
428
|
+
* `tx`. The caller signs + executes `tx` and then renders the URL via
|
|
429
|
+
* `encodeGiftUrl(seed, …)`.
|
|
430
|
+
*/
|
|
431
|
+
export function buildCreateGiftFlow(client, tx, params) {
|
|
432
|
+
const seed = generateGiftSeed();
|
|
433
|
+
const giftKeypair = deriveGiftKeypair(seed);
|
|
434
|
+
const pubkey = giftKeypair.getPublicKey().toRawBytes();
|
|
435
|
+
const giftId = deriveGiftAddress(client, pubkey, params);
|
|
436
|
+
createGift(client, tx, { ...params, pubkey });
|
|
437
|
+
return { tx, seed, giftId, pubkey };
|
|
438
|
+
}
|
|
439
|
+
/**
|
|
440
|
+
* One-shot: derive the gift keypair from `seed`, compute `gift_id`,
|
|
441
|
+
* sign the claim payload bound to `sender`, and add the `claim_share`
|
|
442
|
+
* call to `tx`. Caller signs + executes `tx` with `sender`'s keypair.
|
|
443
|
+
*/
|
|
444
|
+
export async function buildClaimShareFlow(client, tx, params) {
|
|
445
|
+
const giftKeypair = deriveGiftKeypair(params.seed);
|
|
446
|
+
const pubkey = giftKeypair.getPublicKey().toRawBytes();
|
|
447
|
+
const giftId = params.giftId ?? deriveGiftAddress(client, pubkey, params);
|
|
448
|
+
const sig = await signGiftClaim(giftKeypair, giftId, params.sender);
|
|
449
|
+
claimShare(client, tx, { ...params, giftId, sig });
|
|
450
|
+
return { tx, giftId, sig };
|
|
451
|
+
}
|