@x1id/resolve 0.19.1 → 0.21.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 +80 -0
- package/dist/connect.d.ts +20 -8
- package/dist/connect.js +34 -10
- package/dist/gate.js +11 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.js +2 -0
- package/dist/register.js +31 -0
- package/dist/siws.d.ts +310 -0
- package/dist/siws.js +607 -0
- package/dist/subname.js +6 -0
- package/dist/textRecords.js +7 -0
- package/dist/transfer.d.ts +45 -0
- package/dist/transfer.js +56 -0
- package/dist/types.d.ts +4 -0
- package/dist/voucher.d.ts +2 -2
- package/dist/voucher.js +14 -3
- package/dist/x402.js +8 -0
- package/package.json +1 -1
package/dist/transfer.js
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `transfer` — hand an UNTOKENIZED handle to a new owner (a direct gift /
|
|
3
|
+
* reassignment of `handle.owner`). This is the plain-handle counterpart to a
|
|
4
|
+
* tokenized handle's pNFT transfer: a tokenized handle's ownership IS its NFT,
|
|
5
|
+
* so the program REFUSES `transfer` on one (`HandleIsTokenized`) — move the
|
|
6
|
+
* pNFT instead (see `pnftTransfer.ts`).
|
|
7
|
+
*
|
|
8
|
+
* Signed by the handle's CURRENT owner (`has_one = owner` on-chain). The
|
|
9
|
+
* program also refuses the move if the handle is locked (`require_unlocked`)
|
|
10
|
+
* or a live auction on it still has bids. It is NOT gated by the registry
|
|
11
|
+
* pause, so a treasury gift can be made even while registration is paused.
|
|
12
|
+
*
|
|
13
|
+
* Hand-rolled like the rest of this package — no Anchor client, no web3.js.
|
|
14
|
+
* PDAs are NOT derived here (see delegate.ts's module docs); derive
|
|
15
|
+
* `["handle", name]` and `["auction", handle]` with your runtime's canonical
|
|
16
|
+
* `findProgramAddress` and pass them in.
|
|
17
|
+
*/
|
|
18
|
+
import { encodeBase58, decodeBase58_32 } from "./base58.js";
|
|
19
|
+
/** Anchor instruction discriminator: `sha256("global:transfer")[0..8]`. */
|
|
20
|
+
export const TRANSFER_DISCRIMINATOR = Uint8Array.from([
|
|
21
|
+
0xa3, 0x34, 0xc8, 0xe7, 0x8c, 0x03, 0x45, 0xba,
|
|
22
|
+
]);
|
|
23
|
+
function toBytes32(v, what) {
|
|
24
|
+
if (typeof v === "string") {
|
|
25
|
+
const b = decodeBase58_32(v);
|
|
26
|
+
if (!b)
|
|
27
|
+
throw new Error(`${what} is not a valid base58 address`);
|
|
28
|
+
return b;
|
|
29
|
+
}
|
|
30
|
+
if (v.length !== 32)
|
|
31
|
+
throw new Error(`${what} must be exactly 32 bytes`);
|
|
32
|
+
return v;
|
|
33
|
+
}
|
|
34
|
+
function toBase58(v, what) {
|
|
35
|
+
return encodeBase58(toBytes32(v, what));
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Build `transfer(new_owner)`. The data is the 8-byte discriminator followed by
|
|
39
|
+
* the 32-byte new owner; the accounts are `owner` (signer), `handle` (writable)
|
|
40
|
+
* and the read-only `["auction", handle]` PDA, plus any scoped-TLD
|
|
41
|
+
* remaining-accounts. Returns an UNSIGNED instruction — sign with `owner`.
|
|
42
|
+
*/
|
|
43
|
+
export function buildTransferIx(p) {
|
|
44
|
+
const data = new Uint8Array(8 + 32);
|
|
45
|
+
data.set(TRANSFER_DISCRIMINATOR, 0);
|
|
46
|
+
data.set(toBytes32(p.newOwner, "newOwner"), 8);
|
|
47
|
+
const keys = [
|
|
48
|
+
{ pubkey: toBase58(p.owner, "owner"), isSigner: true, isWritable: false },
|
|
49
|
+
{ pubkey: toBase58(p.handle, "handle"), isSigner: false, isWritable: true },
|
|
50
|
+
{ pubkey: toBase58(p.auction, "auction"), isSigner: false, isWritable: false },
|
|
51
|
+
];
|
|
52
|
+
for (const a of p.remainingAccounts ?? []) {
|
|
53
|
+
keys.push({ pubkey: toBase58(a, "remainingAccount"), isSigner: false, isWritable: false });
|
|
54
|
+
}
|
|
55
|
+
return { programId: toBase58(p.programId, "programId"), keys, data };
|
|
56
|
+
}
|
package/dist/types.d.ts
CHANGED
|
@@ -94,6 +94,10 @@ export interface Resolved {
|
|
|
94
94
|
export type Chain = "X1" | "SOL" | "ETH" | "BTC";
|
|
95
95
|
export declare const CHAIN_COIN_TYPE: Readonly<Record<Chain, number>>;
|
|
96
96
|
export type ResolveErrorCode = "unrecognized" | "ambiguous" | "invalid-handle" | "invalid-domain" | "not-found" | "no-record-for-chain" | "rpc-error"
|
|
97
|
+
/** A caller passed a malformed value to an SDK primitive (e.g. a gate that
|
|
98
|
+
* isn't "any-verified"/{kind}/{anyOf}) — a programming error, surfaced as a
|
|
99
|
+
* typed ResolveError rather than a raw TypeError. */
|
|
100
|
+
| "invalid-input"
|
|
97
101
|
/**
|
|
98
102
|
* A reachable namespace exists for this name, but the adapter that would
|
|
99
103
|
* resolve it is not configured on this deployment (e.g. no `ETH_RPC_URL` for
|
package/dist/voucher.d.ts
CHANGED
|
@@ -22,8 +22,8 @@
|
|
|
22
22
|
* escrows the mint price (a snapshot of the live price) into
|
|
23
23
|
* `["voucher", name]` and reserves the voucher slot. `recipient` bound ⇒ the
|
|
24
24
|
* claim registers the handle to that wallet no matter who submits; `null` ⇒
|
|
25
|
-
*
|
|
26
|
-
*
|
|
25
|
+
* a bound recipient (audit S6 — open/recipient-less vouchers were removed as
|
|
26
|
+
* front-runnable; `claimSecretHash` is vestigial and rejected). An optional integrator referrer (the same trailing accounts as
|
|
27
27
|
* `register`, from `integrator.ts`) is snapshotted so the claim can split
|
|
28
28
|
* the escrow. `expiresAt` must be strictly in the future.
|
|
29
29
|
* - `claim_voucher(name)` registers the handle, drawing the fee from the
|
package/dist/voucher.js
CHANGED
|
@@ -22,8 +22,8 @@
|
|
|
22
22
|
* escrows the mint price (a snapshot of the live price) into
|
|
23
23
|
* `["voucher", name]` and reserves the voucher slot. `recipient` bound ⇒ the
|
|
24
24
|
* claim registers the handle to that wallet no matter who submits; `null` ⇒
|
|
25
|
-
*
|
|
26
|
-
*
|
|
25
|
+
* a bound recipient (audit S6 — open/recipient-less vouchers were removed as
|
|
26
|
+
* front-runnable; `claimSecretHash` is vestigial and rejected). An optional integrator referrer (the same trailing accounts as
|
|
27
27
|
* `register`, from `integrator.ts`) is snapshotted so the claim can split
|
|
28
28
|
* the escrow. `expiresAt` must be strictly in the future.
|
|
29
29
|
* - `claim_voucher(name)` registers the handle, drawing the fee from the
|
|
@@ -171,8 +171,19 @@ export function decodePrepaidVoucher(data) {
|
|
|
171
171
|
export function buildCreateVoucherIx(p) {
|
|
172
172
|
const name = encString(p.name);
|
|
173
173
|
const recipient = p.recipient ?? null;
|
|
174
|
+
// Audit S6: the program now REFUSES a recipient-less voucher (the claim tx
|
|
175
|
+
// reveals the secret in cleartext, so an open voucher is front-runnable —
|
|
176
|
+
// error 6106 VoucherMustBeBound). `claimSecretHash` is NO LONGER a second
|
|
177
|
+
// factor: with a recipient mandatory the program stores None and ignores any
|
|
178
|
+
// hash. Throw on both so no integrator believes either still works.
|
|
179
|
+
if (recipient === null) {
|
|
180
|
+
throw new Error("a voucher must bind its recipient (open secret-code vouchers are front-runnable and were disabled on-chain)");
|
|
181
|
+
}
|
|
182
|
+
if (p.claimSecretHash != null) {
|
|
183
|
+
throw new Error("claimSecretHash is removed — vouchers are recipient-bound and carry no claim secret (the program ignores it)");
|
|
184
|
+
}
|
|
174
185
|
const recBytes = recipient === null ? Uint8Array.from([0]) : Uint8Array.from([1, ...toBytes32(recipient, "recipient")]);
|
|
175
|
-
const hashBytes = encOption32(
|
|
186
|
+
const hashBytes = encOption32(null); // S6: always None (a supplied hash throws above)
|
|
176
187
|
const data = new Uint8Array(8 + name.length + 1 + recBytes.length + 8 + hashBytes.length);
|
|
177
188
|
let o = 0;
|
|
178
189
|
data.set(CREATE_VOUCHER_DISCRIMINATOR, o);
|
package/dist/x402.js
CHANGED
|
@@ -60,6 +60,14 @@ export const X402_VERSION = 2;
|
|
|
60
60
|
* and let the buyer fetch their own — the spec allows either).
|
|
61
61
|
*/
|
|
62
62
|
export function buildX402Requirements(p) {
|
|
63
|
+
// W171: payTo / asset / buyer are REQUIRED base58 pubkeys — a missing one
|
|
64
|
+
// otherwise sails through (payTo: undefined) straight into the requirements.
|
|
65
|
+
const PUBKEY_RE = /^[1-9A-HJ-NP-Za-km-z]{32,44}$/;
|
|
66
|
+
for (const [field, value] of [["payTo", p.payTo], ["asset", p.asset], ["buyer", p.buyer]]) {
|
|
67
|
+
if (!PUBKEY_RE.test((value ?? "").trim())) {
|
|
68
|
+
throw new Error(`${field} must be a base58 address (32-44 chars); got ${value === undefined ? "undefined" : `"${value}"`}`);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
63
71
|
if (!/^\d+$/.test(p.amount)) {
|
|
64
72
|
throw new Error("amount must be a decimal string of smallest units (e.g. \"1000000\")");
|
|
65
73
|
}
|