@x1id/resolve 0.2.0 → 0.3.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,130 @@
1
+ /**
2
+ * Prepaid gift-registration vouchers (`PrepaidVoucher`, #7399): instruction
3
+ * builders and account decoding for `create_voucher` / `claim_voucher` /
4
+ * `refund_voucher`.
5
+ *
6
+ * Hand-rolled like the rest of this package — see `delegate.ts` for the
7
+ * web3.js adapter and `wasm.ts` for why PDAs are derived by the caller, not
8
+ * here.
9
+ *
10
+ * # Deriving the PDAs
11
+ *
12
+ * ```ts
13
+ * // the voucher itself
14
+ * PublicKey.findProgramAddressSync([Buffer.from(VOUCHER_SEED), Buffer.from(name)], programId);
15
+ * // the handle the claim will register (canonical name bytes)
16
+ * PublicKey.findProgramAddressSync([Buffer.from("handle"), Buffer.from(name)], programId);
17
+ * ```
18
+ *
19
+ * # Lifecycle (mirror of lib.rs)
20
+ *
21
+ * - `create_voucher(name, handleType, recipient, expiresAt)` escrows the mint
22
+ * price (a snapshot of the live price) into `["voucher", name]` and reserves
23
+ * the voucher slot. `recipient` bound ⇒ the claim registers the handle to
24
+ * that wallet no matter who submits; `null` ⇒ open-code (the claimer owns
25
+ * it). An optional integrator referrer (the same trailing accounts as
26
+ * `register`, from `integrator.ts`) is snapshotted so the claim can split
27
+ * the escrow. `expiresAt` must be strictly in the future.
28
+ * - `claim_voucher(name)` registers the handle, drawing the fee from the
29
+ * escrow (split integrator/treasury per the snapshot), and closes the
30
+ * voucher — rent back to the original payer. The `claimer` pays only the tx
31
+ * fee and the handle's rent, never the mint fee; a relayer may claim for a
32
+ * bound recipient. Supply the integrator wallet iff the voucher carries one.
33
+ * - `refund_voucher(name)` returns the whole escrow (+ rent) to the payer,
34
+ * payer-signed, only at/after `expiresAt`.
35
+ */
36
+ import type { AddressLike, BuiltInstruction, InstructionKey } from "./delegate.js";
37
+ /** Seed prefix of the voucher PDA: `["voucher", name]`. */
38
+ export declare const VOUCHER_SEED = "voucher";
39
+ /** Anchor instruction discriminator `sha256("global:create_voucher")[0..8]`. */
40
+ export declare const CREATE_VOUCHER_DISCRIMINATOR: Uint8Array;
41
+ /** Anchor instruction discriminator `sha256("global:claim_voucher")[0..8]`. */
42
+ export declare const CLAIM_VOUCHER_DISCRIMINATOR: Uint8Array;
43
+ /** Anchor instruction discriminator `sha256("global:refund_voucher")[0..8]`. */
44
+ export declare const REFUND_VOUCHER_DISCRIMINATOR: Uint8Array;
45
+ /** Anchor account discriminator `sha256("account:PrepaidVoucher")[0..8]`. */
46
+ export declare const PREPAID_VOUCHER_DISCRIMINATOR: Uint8Array;
47
+ /** `HandleType` (state.rs): descriptive only, does not gate anything. */
48
+ export declare const HandleType: {
49
+ readonly Human: 0;
50
+ readonly Merchant: 1;
51
+ readonly Org: 2;
52
+ readonly Agent: 3;
53
+ };
54
+ export type HandleTypeValue = (typeof HandleType)[keyof typeof HandleType];
55
+ /** Decoded `PrepaidVoucher` account. */
56
+ export interface PrepaidVoucher {
57
+ /** Who funded it and gets the refund (base58). */
58
+ readonly payer: string;
59
+ /** Canonical name (no `@`). */
60
+ readonly name: string;
61
+ readonly handleType: number;
62
+ /** Escrowed mint fee, in lamports. */
63
+ readonly amount: bigint;
64
+ /** Bound recipient (base58) or null for an open-code voucher. */
65
+ readonly recipient: string | null;
66
+ /** Integrator referrer (base58) or null. */
67
+ readonly integrator: string | null;
68
+ /** Integrator share in basis points (meaningful only if `integrator`). */
69
+ readonly integratorRateBps: number;
70
+ readonly expiresAt: bigint;
71
+ readonly createdAt: bigint;
72
+ readonly bump: number;
73
+ }
74
+ /**
75
+ * Decode a `PrepaidVoucher` account's raw data, or null if not one. Parsed
76
+ * sequentially (Borsh): the two `Option<Pubkey>` fields are 1 byte when
77
+ * absent, 33 when present, so fixed offsets after them would be wrong.
78
+ */
79
+ export declare function decodePrepaidVoucher(data: Uint8Array): PrepaidVoucher | null;
80
+ export interface CreateVoucherParams {
81
+ readonly programId: AddressLike;
82
+ /** Funds the escrow + the voucher's rent. Signer. */
83
+ readonly payer: AddressLike;
84
+ /** The `["config"]` PDA. */
85
+ readonly config: AddressLike;
86
+ /** The `["voucher", name]` PDA. */
87
+ readonly voucher: AddressLike;
88
+ /** The `["handle", name]` PDA — must be unregistered. */
89
+ readonly handle: AddressLike;
90
+ /** Canonical name (no `@`). */
91
+ readonly name: string;
92
+ readonly handleType: HandleTypeValue;
93
+ /** Bind the gift to this wallet, or null for open-code. */
94
+ readonly recipient?: AddressLike | null;
95
+ /** Unix seconds; must be strictly in the future. */
96
+ readonly expiresAt: bigint | number;
97
+ /** Optional integrator pair from `integratorAccountsForCreateVoucher`. */
98
+ readonly integratorAccounts?: readonly InstructionKey[];
99
+ }
100
+ /** Build `create_voucher`. */
101
+ export declare function buildCreateVoucherIx(p: CreateVoucherParams): BuiltInstruction;
102
+ export interface ClaimVoucherParams {
103
+ readonly programId: AddressLike;
104
+ /** Pays the tx fee + the handle's rent (NOT the mint fee). Signer. May be a
105
+ * relayer when the voucher binds a recipient. */
106
+ readonly claimer: AddressLike;
107
+ readonly config: AddressLike;
108
+ /** `Config.treasury`. */
109
+ readonly treasury: AddressLike;
110
+ readonly voucher: AddressLike;
111
+ /** The voucher's recorded payer — receives the voucher's rent on close. */
112
+ readonly voucherPayer: AddressLike;
113
+ /** The `["handle", name]` PDA being registered. */
114
+ readonly handle: AddressLike;
115
+ readonly name: string;
116
+ /** The integrator wallet — REQUIRED iff the voucher carries one; must equal
117
+ * the voucher's `integrator`. Omit otherwise. */
118
+ readonly integrator?: AddressLike;
119
+ }
120
+ /** Build `claim_voucher`. */
121
+ export declare function buildClaimVoucherIx(p: ClaimVoucherParams): BuiltInstruction;
122
+ export interface RefundVoucherParams {
123
+ readonly programId: AddressLike;
124
+ /** The original payer. Signer; receives escrow + rent. */
125
+ readonly payer: AddressLike;
126
+ readonly voucher: AddressLike;
127
+ readonly name: string;
128
+ }
129
+ /** Build `refund_voucher` — payer-signed, only valid at/after `expiresAt`. */
130
+ export declare function buildRefundVoucherIx(p: RefundVoucherParams): BuiltInstruction;
@@ -0,0 +1,185 @@
1
+ /**
2
+ * Prepaid gift-registration vouchers (`PrepaidVoucher`, #7399): instruction
3
+ * builders and account decoding for `create_voucher` / `claim_voucher` /
4
+ * `refund_voucher`.
5
+ *
6
+ * Hand-rolled like the rest of this package — see `delegate.ts` for the
7
+ * web3.js adapter and `wasm.ts` for why PDAs are derived by the caller, not
8
+ * here.
9
+ *
10
+ * # Deriving the PDAs
11
+ *
12
+ * ```ts
13
+ * // the voucher itself
14
+ * PublicKey.findProgramAddressSync([Buffer.from(VOUCHER_SEED), Buffer.from(name)], programId);
15
+ * // the handle the claim will register (canonical name bytes)
16
+ * PublicKey.findProgramAddressSync([Buffer.from("handle"), Buffer.from(name)], programId);
17
+ * ```
18
+ *
19
+ * # Lifecycle (mirror of lib.rs)
20
+ *
21
+ * - `create_voucher(name, handleType, recipient, expiresAt)` escrows the mint
22
+ * price (a snapshot of the live price) into `["voucher", name]` and reserves
23
+ * the voucher slot. `recipient` bound ⇒ the claim registers the handle to
24
+ * that wallet no matter who submits; `null` ⇒ open-code (the claimer owns
25
+ * it). An optional integrator referrer (the same trailing accounts as
26
+ * `register`, from `integrator.ts`) is snapshotted so the claim can split
27
+ * the escrow. `expiresAt` must be strictly in the future.
28
+ * - `claim_voucher(name)` registers the handle, drawing the fee from the
29
+ * escrow (split integrator/treasury per the snapshot), and closes the
30
+ * voucher — rent back to the original payer. The `claimer` pays only the tx
31
+ * fee and the handle's rent, never the mint fee; a relayer may claim for a
32
+ * bound recipient. Supply the integrator wallet iff the voucher carries one.
33
+ * - `refund_voucher(name)` returns the whole escrow (+ rent) to the payer,
34
+ * payer-signed, only at/after `expiresAt`.
35
+ */
36
+ import { encodeBase58, decodeBase58_32 } from "./base58.js";
37
+ /** Seed prefix of the voucher PDA: `["voucher", name]`. */
38
+ export const VOUCHER_SEED = "voucher";
39
+ /** Anchor instruction discriminator `sha256("global:create_voucher")[0..8]`. */
40
+ export const CREATE_VOUCHER_DISCRIMINATOR = Uint8Array.from([22, 97, 32, 21, 104, 137, 188, 143]);
41
+ /** Anchor instruction discriminator `sha256("global:claim_voucher")[0..8]`. */
42
+ export const CLAIM_VOUCHER_DISCRIMINATOR = Uint8Array.from([229, 30, 138, 35, 188, 87, 230, 7]);
43
+ /** Anchor instruction discriminator `sha256("global:refund_voucher")[0..8]`. */
44
+ export const REFUND_VOUCHER_DISCRIMINATOR = Uint8Array.from([27, 159, 115, 120, 212, 202, 186, 248]);
45
+ /** Anchor account discriminator `sha256("account:PrepaidVoucher")[0..8]`. */
46
+ export const PREPAID_VOUCHER_DISCRIMINATOR = Uint8Array.from([159, 185, 203, 226, 62, 6, 57, 194]);
47
+ /** `HandleType` (state.rs): descriptive only, does not gate anything. */
48
+ export const HandleType = { Human: 0, Merchant: 1, Org: 2, Agent: 3 };
49
+ const SYSTEM_PROGRAM = "11111111111111111111111111111111";
50
+ function toBytes32(v, what) {
51
+ if (typeof v === "string") {
52
+ const b = decodeBase58_32(v);
53
+ if (!b)
54
+ throw new Error(`${what} is not a valid base58 address`);
55
+ return b;
56
+ }
57
+ if (v.length !== 32)
58
+ throw new Error(`${what} must be exactly 32 bytes`);
59
+ return v;
60
+ }
61
+ function toBase58(v, what) {
62
+ return encodeBase58(toBytes32(v, what));
63
+ }
64
+ /** Borsh `String`: u32 LE length + UTF-8 bytes. */
65
+ function encString(s) {
66
+ const bytes = new TextEncoder().encode(s);
67
+ const out = new Uint8Array(4 + bytes.length);
68
+ new DataView(out.buffer).setUint32(0, bytes.length, true);
69
+ out.set(bytes, 4);
70
+ return out;
71
+ }
72
+ function encU64(v) {
73
+ const out = new Uint8Array(8);
74
+ new DataView(out.buffer).setBigInt64(0, v, true);
75
+ return out;
76
+ }
77
+ /**
78
+ * Decode a `PrepaidVoucher` account's raw data, or null if not one. Parsed
79
+ * sequentially (Borsh): the two `Option<Pubkey>` fields are 1 byte when
80
+ * absent, 33 when present, so fixed offsets after them would be wrong.
81
+ */
82
+ export function decodePrepaidVoucher(data) {
83
+ if (data.length < 8 + 32 + 32 + 1 + 1 + 8 + 1 + 1 + 2 + 8 + 8 + 1)
84
+ return null;
85
+ for (let i = 0; i < 8; i++)
86
+ if (data[i] !== PREPAID_VOUCHER_DISCRIMINATOR[i])
87
+ return null;
88
+ const view = new DataView(data.buffer, data.byteOffset, data.byteLength);
89
+ let o = 8;
90
+ const payer = encodeBase58(data.slice(o, o + 32));
91
+ o += 32;
92
+ const nameBytes = data.slice(o, o + 32);
93
+ o += 32;
94
+ const nameLen = data[o];
95
+ o += 1;
96
+ const name = new TextDecoder().decode(nameBytes.slice(0, nameLen));
97
+ const handleType = data[o];
98
+ o += 1;
99
+ const amount = view.getBigUint64(o, true);
100
+ o += 8;
101
+ const recipientTag = data[o];
102
+ o += 1;
103
+ let recipient = null;
104
+ if (recipientTag === 1) {
105
+ recipient = encodeBase58(data.slice(o, o + 32));
106
+ o += 32;
107
+ }
108
+ const integratorTag = data[o];
109
+ o += 1;
110
+ let integrator = null;
111
+ if (integratorTag === 1) {
112
+ integrator = encodeBase58(data.slice(o, o + 32));
113
+ o += 32;
114
+ }
115
+ const integratorRateBps = view.getUint16(o, true);
116
+ o += 2;
117
+ const expiresAt = view.getBigInt64(o, true);
118
+ o += 8;
119
+ const createdAt = view.getBigInt64(o, true);
120
+ o += 8;
121
+ const bump = data[o];
122
+ return { payer, name, handleType, amount, recipient, integrator, integratorRateBps, expiresAt, createdAt, bump };
123
+ }
124
+ /** Build `create_voucher`. */
125
+ export function buildCreateVoucherIx(p) {
126
+ const name = encString(p.name);
127
+ const recipient = p.recipient ?? null;
128
+ const recBytes = recipient === null ? Uint8Array.from([0]) : Uint8Array.from([1, ...toBytes32(recipient, "recipient")]);
129
+ const data = new Uint8Array(8 + name.length + 1 + recBytes.length + 8);
130
+ let o = 0;
131
+ data.set(CREATE_VOUCHER_DISCRIMINATOR, o);
132
+ o += 8;
133
+ data.set(name, o);
134
+ o += name.length;
135
+ data[o] = p.handleType;
136
+ o += 1;
137
+ data.set(recBytes, o);
138
+ o += recBytes.length;
139
+ data.set(encU64(BigInt(p.expiresAt)), o);
140
+ const keys = [
141
+ { pubkey: toBase58(p.payer, "payer"), isSigner: true, isWritable: true },
142
+ { pubkey: toBase58(p.config, "config"), isSigner: false, isWritable: false },
143
+ { pubkey: toBase58(p.voucher, "voucher"), isSigner: false, isWritable: true },
144
+ { pubkey: toBase58(p.handle, "handle"), isSigner: false, isWritable: false },
145
+ { pubkey: SYSTEM_PROGRAM, isSigner: false, isWritable: false },
146
+ ];
147
+ if (p.integratorAccounts)
148
+ keys.push(...p.integratorAccounts);
149
+ return { programId: toBase58(p.programId, "programId"), keys, data };
150
+ }
151
+ /** Build `claim_voucher`. */
152
+ export function buildClaimVoucherIx(p) {
153
+ const name = encString(p.name);
154
+ const data = new Uint8Array(8 + name.length);
155
+ data.set(CLAIM_VOUCHER_DISCRIMINATOR, 0);
156
+ data.set(name, 8);
157
+ const keys = [
158
+ { pubkey: toBase58(p.claimer, "claimer"), isSigner: true, isWritable: true },
159
+ { pubkey: toBase58(p.config, "config"), isSigner: false, isWritable: true },
160
+ { pubkey: toBase58(p.treasury, "treasury"), isSigner: false, isWritable: true },
161
+ { pubkey: toBase58(p.voucher, "voucher"), isSigner: false, isWritable: true },
162
+ { pubkey: toBase58(p.voucherPayer, "voucherPayer"), isSigner: false, isWritable: true },
163
+ { pubkey: toBase58(p.handle, "handle"), isSigner: false, isWritable: true },
164
+ { pubkey: SYSTEM_PROGRAM, isSigner: false, isWritable: false },
165
+ ];
166
+ if (p.integrator !== undefined) {
167
+ keys.push({ pubkey: toBase58(p.integrator, "integrator"), isSigner: false, isWritable: true });
168
+ }
169
+ return { programId: toBase58(p.programId, "programId"), keys, data };
170
+ }
171
+ /** Build `refund_voucher` — payer-signed, only valid at/after `expiresAt`. */
172
+ export function buildRefundVoucherIx(p) {
173
+ const name = encString(p.name);
174
+ const data = new Uint8Array(8 + name.length);
175
+ data.set(REFUND_VOUCHER_DISCRIMINATOR, 0);
176
+ data.set(name, 8);
177
+ return {
178
+ programId: toBase58(p.programId, "programId"),
179
+ keys: [
180
+ { pubkey: toBase58(p.payer, "payer"), isSigner: true, isWritable: true },
181
+ { pubkey: toBase58(p.voucher, "voucher"), isSigner: false, isWritable: true },
182
+ ],
183
+ data,
184
+ };
185
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@x1id/resolve",
3
- "version": "0.2.0",
3
+ "version": "0.3.0",
4
4
  "description": "Resolve @handles and X1NS names on X1. Never silently picks between namespaces.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -17,7 +17,7 @@
17
17
  "build": "tsc -p tsconfig.json",
18
18
  "test": "node --test test/*.test.js",
19
19
  "lint:package": "publint",
20
- "prepublishOnly": "npm run build"
20
+ "prepublishOnly": "cargo build --release -p x1-resolve-wasm --target wasm32-unknown-unknown --manifest-path ../Cargo.toml && node ../web/verify-wasm.mjs wasm/x1_resolve_wasm.wasm ../target/wasm32-unknown-unknown/release/x1_resolve_wasm.wasm && npm run build"
21
21
  },
22
22
  "keywords": ["x1", "x1id", "solana", "svm", "naming", "x1ns", "handles", "wallet", "resolver", "web3"],
23
23
  "homepage": "https://x1id.io",
Binary file
package/LICENSE DELETED
@@ -1,21 +0,0 @@
1
- MIT License
2
-
3
- Copyright (c) 2026 Fortiblox
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining a copy
6
- of this software and associated documentation files (the "Software"), to deal
7
- in the Software without restriction, including without limitation the rights
8
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- copies of the Software, and to permit persons to whom the Software is
10
- furnished to do so, subject to the following conditions:
11
-
12
- The above copyright notice and this permission notice shall be included in all
13
- copies or substantial portions of the Software.
14
-
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
- SOFTWARE.