phygital-token-mcp 0.1.1
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 +59 -0
- package/cursor-mcp.example.json +8 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +481 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/docs.d.ts +17 -0
- package/dist/lib/docs.js +121 -0
- package/dist/lib/docs.js.map +1 -0
- package/dist/lib/format.d.ts +13 -0
- package/dist/lib/format.js +12 -0
- package/dist/lib/format.js.map +1 -0
- package/dist/lib/gating-json.d.ts +127 -0
- package/dist/lib/gating-json.js +346 -0
- package/dist/lib/gating-json.js.map +1 -0
- package/dist/lib/graphify.d.ts +2 -0
- package/dist/lib/graphify.js +35 -0
- package/dist/lib/graphify.js.map +1 -0
- package/dist/lib/instructions.d.ts +131 -0
- package/dist/lib/instructions.js +232 -0
- package/dist/lib/instructions.js.map +1 -0
- package/dist/lib/paths.d.ts +14 -0
- package/dist/lib/paths.js +77 -0
- package/dist/lib/paths.js.map +1 -0
- package/dist/lib/rpc.d.ts +3 -0
- package/dist/lib/rpc.js +22 -0
- package/dist/lib/rpc.js.map +1 -0
- package/dist/lib/sdk-surface.d.ts +33 -0
- package/dist/lib/sdk-surface.js +101 -0
- package/dist/lib/sdk-surface.js.map +1 -0
- package/dist/lib/verification.d.ts +43 -0
- package/dist/lib/verification.js +166 -0
- package/dist/lib/verification.js.map +1 -0
- package/docs/building-on-phygital/overview.md +46 -0
- package/docs/building-on-phygital/rust-cpi.md +55 -0
- package/docs/glossary.md +43 -0
- package/docs/sdk/surface-area.md +77 -0
- package/docs/verification/methods.md +58 -0
- package/docs/verification/overview.md +70 -0
- package/docs/verification/verify-asset-composable.md +97 -0
- package/package.json +52 -0
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import { readFile } from "node:fs/promises";
|
|
2
|
+
import { pathExists, resolveRustVerifyAssetPath, resolveVerifyAssetTsPath, resolveVerifyTsPath, } from "./paths.js";
|
|
3
|
+
export const SDK_SURFACE = {
|
|
4
|
+
mint: [
|
|
5
|
+
"buildCreateMintInstructions",
|
|
6
|
+
"buildMintTokenInstructions",
|
|
7
|
+
"parseSecp256r1Pubkey",
|
|
8
|
+
"parseCredentialId",
|
|
9
|
+
"validateMetadataFields",
|
|
10
|
+
],
|
|
11
|
+
transfer: [
|
|
12
|
+
"beginTransfer",
|
|
13
|
+
"authenticatePasskeyForTransfer",
|
|
14
|
+
"completeTransfer",
|
|
15
|
+
],
|
|
16
|
+
verifyAssetComposable: [
|
|
17
|
+
"beginVerifyAsset",
|
|
18
|
+
"authenticatePasskeyForVerifyAsset",
|
|
19
|
+
"buildVerifyAssetArgs",
|
|
20
|
+
"completeVerifyAsset",
|
|
21
|
+
],
|
|
22
|
+
verification: [
|
|
23
|
+
"verifyDynamicUrl",
|
|
24
|
+
"verifyDynamicUrlWithoutCounterCheck",
|
|
25
|
+
"verifyWithChallengeResponse",
|
|
26
|
+
"verifyWithChallengeResponseOverNfc",
|
|
27
|
+
],
|
|
28
|
+
onChainComposition: {
|
|
29
|
+
patternA_inspect: {
|
|
30
|
+
client: ["beginVerifyAsset", "completeVerifyAsset"],
|
|
31
|
+
transaction: ["secp256r1_verify", "verify_asset", "your_program_ix"],
|
|
32
|
+
program: "inspect instructions sysvar for verify_asset message",
|
|
33
|
+
},
|
|
34
|
+
patternB_cpi: {
|
|
35
|
+
client: ["beginVerifyAsset", "buildVerifyAssetArgs"],
|
|
36
|
+
transaction: ["secp256r1_verify", "your_program_ix"],
|
|
37
|
+
program: "CPI verify_asset via VerifyAssetCpiBuilder",
|
|
38
|
+
},
|
|
39
|
+
},
|
|
40
|
+
assetLookup: [
|
|
41
|
+
"findAssetPda",
|
|
42
|
+
"fetchAssetFromCredentialId",
|
|
43
|
+
"fetchAllAssetsFromOwner",
|
|
44
|
+
"fetchAssetDisplayInfo",
|
|
45
|
+
"resolveMedia",
|
|
46
|
+
],
|
|
47
|
+
gating: [
|
|
48
|
+
"Gating",
|
|
49
|
+
"GatingTraitValue",
|
|
50
|
+
"formatGatingPredicate",
|
|
51
|
+
"summarizeGatingEvaluationFailure",
|
|
52
|
+
"summarizeGatingFailure",
|
|
53
|
+
"summarizeGatingTierFailure",
|
|
54
|
+
"evaluateAssetGating",
|
|
55
|
+
],
|
|
56
|
+
gatingTypes: [
|
|
57
|
+
"EvaluateAssetGatingOptions",
|
|
58
|
+
"GatingFilter",
|
|
59
|
+
"GatingAssetPredicate",
|
|
60
|
+
"GatingTier",
|
|
61
|
+
"GatingEvaluationResult",
|
|
62
|
+
"GatingFilterResult",
|
|
63
|
+
"GatingTierEvaluationResult",
|
|
64
|
+
"GatingTiersEvaluationResult",
|
|
65
|
+
],
|
|
66
|
+
generated: [
|
|
67
|
+
"getCreateMintInstructionAsync",
|
|
68
|
+
"getMintTokenInstructionAsync",
|
|
69
|
+
"getExecuteTransferInstructionAsync",
|
|
70
|
+
"getVerifyAssetInstruction",
|
|
71
|
+
"getSetLockStateInstruction",
|
|
72
|
+
"fetchAsset",
|
|
73
|
+
"findProgramAuthorityPda",
|
|
74
|
+
"PHYGITAL_TOKEN_PROGRAM_ADDRESS",
|
|
75
|
+
],
|
|
76
|
+
rustClient: {
|
|
77
|
+
crate: "phygital-token-client",
|
|
78
|
+
path: "clients/rust/phygital-token",
|
|
79
|
+
features: ["anchor", "fetch"],
|
|
80
|
+
cpi: ["VerifyAssetCpi", "VerifyAssetCpiBuilder", "VerifyAssetInstructionArgs"],
|
|
81
|
+
types: ["Asset", "Secp256r1VerifyArgs", "AssetType"],
|
|
82
|
+
},
|
|
83
|
+
};
|
|
84
|
+
export async function readSourceExcerpt(which, maxLines = 120) {
|
|
85
|
+
const paths = {
|
|
86
|
+
"verify.ts": resolveVerifyTsPath(),
|
|
87
|
+
"verifyAsset.ts": resolveVerifyAssetTsPath(),
|
|
88
|
+
"rust_verify_asset.rs": resolveRustVerifyAssetPath(),
|
|
89
|
+
};
|
|
90
|
+
const filePath = paths[which];
|
|
91
|
+
if (!(await pathExists(filePath))) {
|
|
92
|
+
throw new Error(`Source file not found: ${filePath}. Set PHYGITAL_TOKEN_REPO_ROOT to a cloned phygital-token repo to use read_sdk_source.`);
|
|
93
|
+
}
|
|
94
|
+
const content = await readFile(filePath, "utf8");
|
|
95
|
+
const lines = content.split("\n").slice(0, maxLines);
|
|
96
|
+
return {
|
|
97
|
+
path: filePath,
|
|
98
|
+
excerpt: lines.join("\n") + (content.split("\n").length > maxLines ? "\n// ..." : ""),
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
//# sourceMappingURL=sdk-surface.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sdk-surface.js","sourceRoot":"","sources":["../../src/lib/sdk-surface.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
export type VerificationUseCase = "product_page_lookup" | "deep_link_from_prior_scan" | "offline_identification" | "login_ui_only" | "onchain_standalone_verify" | "onchain_inspect_verify_asset" | "onchain_cpi_verify_asset" | "transfer_ownership" | "wallet_holdings_gate" | "native_mobile_app";
|
|
2
|
+
export type OnChainCompositionPattern = "inspect" | "cpi" | "standalone";
|
|
3
|
+
export type VerificationRecommendation = {
|
|
4
|
+
method: string;
|
|
5
|
+
sdkExports: string[];
|
|
6
|
+
requiresTap: boolean;
|
|
7
|
+
onChain: boolean;
|
|
8
|
+
onChainPattern?: OnChainCompositionPattern;
|
|
9
|
+
rationale: string;
|
|
10
|
+
docIds: string[];
|
|
11
|
+
cautions?: string[];
|
|
12
|
+
};
|
|
13
|
+
export declare const ON_CHAIN_PATTERNS: {
|
|
14
|
+
readonly inspect: {
|
|
15
|
+
readonly id: "inspect";
|
|
16
|
+
readonly name: "Pattern A — client posts verify_asset, program inspects";
|
|
17
|
+
readonly clientTransaction: readonly ["secp256r1_verify", "verify_asset", "your_program_ix"];
|
|
18
|
+
readonly clientSdk: readonly ["beginVerifyAsset", "completeVerifyAsset", "getVerifyAssetInstruction"];
|
|
19
|
+
readonly programRust: "Scan instructions sysvar for preceding verify_asset; check message bytes";
|
|
20
|
+
readonly reference: "programs/phygital-spend";
|
|
21
|
+
};
|
|
22
|
+
readonly cpi: {
|
|
23
|
+
readonly id: "cpi";
|
|
24
|
+
readonly name: "Pattern B — client posts secp256r1_verify, program CPIs verify_asset";
|
|
25
|
+
readonly clientTransaction: readonly ["secp256r1_verify", "your_program_ix"];
|
|
26
|
+
readonly clientSdk: readonly ["beginVerifyAsset", "buildVerifyAssetArgs"];
|
|
27
|
+
readonly programRust: "VerifyAssetCpiBuilder from phygital-token-client";
|
|
28
|
+
readonly reference: "clients/rust/phygital-token";
|
|
29
|
+
};
|
|
30
|
+
readonly standalone: {
|
|
31
|
+
readonly id: "standalone";
|
|
32
|
+
readonly name: "Standalone on-chain verify_asset (no custom program)";
|
|
33
|
+
readonly clientTransaction: readonly ["secp256r1_verify", "verify_asset"];
|
|
34
|
+
readonly clientSdk: readonly ["beginVerifyAsset", "completeVerifyAsset"];
|
|
35
|
+
readonly programRust: "N/A";
|
|
36
|
+
};
|
|
37
|
+
};
|
|
38
|
+
export declare function recommendVerification(useCase: VerificationUseCase): VerificationRecommendation;
|
|
39
|
+
export declare function listVerificationUseCases(): Array<{
|
|
40
|
+
id: VerificationUseCase;
|
|
41
|
+
summary: string;
|
|
42
|
+
}>;
|
|
43
|
+
export declare const VERIFICATION_DECISION_TREE: string;
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
export const ON_CHAIN_PATTERNS = {
|
|
2
|
+
inspect: {
|
|
3
|
+
id: "inspect",
|
|
4
|
+
name: "Pattern A — client posts verify_asset, program inspects",
|
|
5
|
+
clientTransaction: ["secp256r1_verify", "verify_asset", "your_program_ix"],
|
|
6
|
+
clientSdk: ["beginVerifyAsset", "completeVerifyAsset", "getVerifyAssetInstruction"],
|
|
7
|
+
programRust: "Scan instructions sysvar for preceding verify_asset; check message bytes",
|
|
8
|
+
reference: "programs/phygital-spend",
|
|
9
|
+
},
|
|
10
|
+
cpi: {
|
|
11
|
+
id: "cpi",
|
|
12
|
+
name: "Pattern B — client posts secp256r1_verify, program CPIs verify_asset",
|
|
13
|
+
clientTransaction: ["secp256r1_verify", "your_program_ix"],
|
|
14
|
+
clientSdk: ["beginVerifyAsset", "buildVerifyAssetArgs"],
|
|
15
|
+
programRust: "VerifyAssetCpiBuilder from phygital-token-client",
|
|
16
|
+
reference: "clients/rust/phygital-token",
|
|
17
|
+
},
|
|
18
|
+
standalone: {
|
|
19
|
+
id: "standalone",
|
|
20
|
+
name: "Standalone on-chain verify_asset (no custom program)",
|
|
21
|
+
clientTransaction: ["secp256r1_verify", "verify_asset"],
|
|
22
|
+
clientSdk: ["beginVerifyAsset", "completeVerifyAsset"],
|
|
23
|
+
programRust: "N/A",
|
|
24
|
+
},
|
|
25
|
+
};
|
|
26
|
+
const RECOMMENDATIONS = {
|
|
27
|
+
product_page_lookup: {
|
|
28
|
+
method: "identification — verifyDynamicUrl",
|
|
29
|
+
sdkExports: ["verifyDynamicUrl"],
|
|
30
|
+
requiresTap: false,
|
|
31
|
+
onChain: false,
|
|
32
|
+
rationale: "User already scanned; signed URL params identify the asset without a second tap.",
|
|
33
|
+
docIds: ["verification:methods", "verification:overview"],
|
|
34
|
+
},
|
|
35
|
+
deep_link_from_prior_scan: {
|
|
36
|
+
method: "identification — verifyDynamicUrl",
|
|
37
|
+
sdkExports: ["verifyDynamicUrl"],
|
|
38
|
+
requiresTap: false,
|
|
39
|
+
onChain: false,
|
|
40
|
+
rationale: "Signed deep-link params from an earlier tap.",
|
|
41
|
+
docIds: ["verification:methods"],
|
|
42
|
+
},
|
|
43
|
+
offline_identification: {
|
|
44
|
+
method: "identification — verifyDynamicUrlWithoutCounterCheck",
|
|
45
|
+
sdkExports: ["verifyDynamicUrlWithoutCounterCheck"],
|
|
46
|
+
requiresTap: false,
|
|
47
|
+
onChain: false,
|
|
48
|
+
rationale: "Local signature check only. Not for authorization.",
|
|
49
|
+
docIds: ["verification:methods"],
|
|
50
|
+
cautions: ["Copied links can be replayed."],
|
|
51
|
+
},
|
|
52
|
+
login_ui_only: {
|
|
53
|
+
method: "authentication off-chain — verifyWithChallengeResponse",
|
|
54
|
+
sdkExports: ["verifyWithChallengeResponse", "verifyWithChallengeResponseOverNfc"],
|
|
55
|
+
requiresTap: true,
|
|
56
|
+
onChain: false,
|
|
57
|
+
rationale: "Live NFC tap verified in the client. Optional message binds the WebAuthn challenge (UTF-8). No on-chain transaction.",
|
|
58
|
+
docIds: ["verification:methods", "verification:overview"],
|
|
59
|
+
},
|
|
60
|
+
onchain_standalone_verify: {
|
|
61
|
+
method: "on-chain verify_asset only",
|
|
62
|
+
sdkExports: ["beginVerifyAsset", "authenticatePasskeyForVerifyAsset", "completeVerifyAsset"],
|
|
63
|
+
requiresTap: true,
|
|
64
|
+
onChain: true,
|
|
65
|
+
onChainPattern: "standalone",
|
|
66
|
+
rationale: "Record passkey proof on-chain without a custom program.",
|
|
67
|
+
docIds: ["verification:verify-asset-composable"],
|
|
68
|
+
},
|
|
69
|
+
onchain_inspect_verify_asset: {
|
|
70
|
+
method: "Pattern A — client posts verify_asset, your program inspects message",
|
|
71
|
+
sdkExports: [
|
|
72
|
+
"beginVerifyAsset",
|
|
73
|
+
"authenticatePasskeyForVerifyAsset",
|
|
74
|
+
"completeVerifyAsset",
|
|
75
|
+
"getVerifyAssetInstruction",
|
|
76
|
+
],
|
|
77
|
+
requiresTap: true,
|
|
78
|
+
onChain: true,
|
|
79
|
+
onChainPattern: "inspect",
|
|
80
|
+
rationale: "Client includes verify_asset in the tx. Your program scans instructions sysvar for that verify_asset and validates message bytes.",
|
|
81
|
+
docIds: [
|
|
82
|
+
"verification:verify-asset-composable",
|
|
83
|
+
"building-on-phygital:overview",
|
|
84
|
+
"building-on-phygital:rust-cpi",
|
|
85
|
+
],
|
|
86
|
+
},
|
|
87
|
+
onchain_cpi_verify_asset: {
|
|
88
|
+
method: "Pattern B — buildVerifyAssetArgs, your program CPIs verify_asset",
|
|
89
|
+
sdkExports: [
|
|
90
|
+
"beginVerifyAsset",
|
|
91
|
+
"authenticatePasskeyForVerifyAsset",
|
|
92
|
+
"buildVerifyAssetArgs",
|
|
93
|
+
],
|
|
94
|
+
requiresTap: true,
|
|
95
|
+
onChain: true,
|
|
96
|
+
onChainPattern: "cpi",
|
|
97
|
+
rationale: "Client includes secp256r1_verify + your ix only. Your program CPIs verify_asset using args from buildVerifyAssetArgs.",
|
|
98
|
+
docIds: [
|
|
99
|
+
"verification:verify-asset-composable",
|
|
100
|
+
"building-on-phygital:rust-cpi",
|
|
101
|
+
"building-on-phygital:overview",
|
|
102
|
+
],
|
|
103
|
+
},
|
|
104
|
+
transfer_ownership: {
|
|
105
|
+
method: "transfer — beginTransfer / completeTransfer",
|
|
106
|
+
sdkExports: ["beginTransfer", "authenticatePasskeyForTransfer", "completeTransfer"],
|
|
107
|
+
requiresTap: true,
|
|
108
|
+
onChain: true,
|
|
109
|
+
rationale: "Token claim uses execute_transfer, not verify_asset.",
|
|
110
|
+
docIds: ["verification:overview"],
|
|
111
|
+
cautions: ["Do not use verifyDynamicUrl for transfers."],
|
|
112
|
+
},
|
|
113
|
+
wallet_holdings_gate: {
|
|
114
|
+
method: "gating — evaluateAssetGating",
|
|
115
|
+
sdkExports: ["evaluateAssetGating", "Gating", "GatingTraitValue"],
|
|
116
|
+
requiresTap: false,
|
|
117
|
+
onChain: false,
|
|
118
|
+
rationale: "Wallet holdings via DAS. No passkey tap.",
|
|
119
|
+
docIds: ["gating:overview"],
|
|
120
|
+
},
|
|
121
|
+
native_mobile_app: {
|
|
122
|
+
method: "authentication off-chain — verifyWithChallengeResponseOverNfc",
|
|
123
|
+
sdkExports: ["verifyWithChallengeResponseOverNfc"],
|
|
124
|
+
requiresTap: true,
|
|
125
|
+
onChain: false,
|
|
126
|
+
rationale: "Native NFC transceive. Off-chain only; use beginVerifyAsset for on-chain proof.",
|
|
127
|
+
docIds: ["verification:methods"],
|
|
128
|
+
},
|
|
129
|
+
};
|
|
130
|
+
export function recommendVerification(useCase) {
|
|
131
|
+
return RECOMMENDATIONS[useCase];
|
|
132
|
+
}
|
|
133
|
+
export function listVerificationUseCases() {
|
|
134
|
+
return [
|
|
135
|
+
{ id: "product_page_lookup", summary: "Product page from prior scan URL" },
|
|
136
|
+
{ id: "deep_link_from_prior_scan", summary: "App opens from signed deep link" },
|
|
137
|
+
{ id: "offline_identification", summary: "Identify asset offline (weak replay)" },
|
|
138
|
+
{ id: "login_ui_only", summary: "Off-chain tap-to-login (no chain tx)" },
|
|
139
|
+
{ id: "onchain_standalone_verify", summary: "On-chain verify_asset only" },
|
|
140
|
+
{
|
|
141
|
+
id: "onchain_inspect_verify_asset",
|
|
142
|
+
summary: "Pattern A: client posts verify_asset, your program inspects message",
|
|
143
|
+
},
|
|
144
|
+
{
|
|
145
|
+
id: "onchain_cpi_verify_asset",
|
|
146
|
+
summary: "Pattern B: buildVerifyAssetArgs, your program CPIs verify_asset",
|
|
147
|
+
},
|
|
148
|
+
{ id: "transfer_ownership", summary: "Claim/transfer token to new owner" },
|
|
149
|
+
{ id: "wallet_holdings_gate", summary: "Gate by wallet NFTs/tokens" },
|
|
150
|
+
{ id: "native_mobile_app", summary: "Native app off-chain authentication" },
|
|
151
|
+
];
|
|
152
|
+
}
|
|
153
|
+
export const VERIFICATION_DECISION_TREE = `
|
|
154
|
+
Identification vs Authentication
|
|
155
|
+
├── Need holder present NOW?
|
|
156
|
+
│ NO → verifyDynamicUrl / verifyDynamicUrlWithoutCounterCheck
|
|
157
|
+
│ YES → Need on-chain proof?
|
|
158
|
+
│ NO → verifyWithChallengeResponse (web) / OverNfc (native) — off-chain only
|
|
159
|
+
│ YES → beginVerifyAsset composable flow:
|
|
160
|
+
│ Pattern A: [secp256r1_verify, verify_asset, your_ix] — program inspects sysvar
|
|
161
|
+
│ Pattern B: [secp256r1_verify, your_ix] — program CPIs verify_asset
|
|
162
|
+
└── Transfer ownership? → beginTransfer → completeTransfer
|
|
163
|
+
|
|
164
|
+
verifyWithChallengeResponse never submits verify_asset. On-chain proof always uses beginVerifyAsset.
|
|
165
|
+
`.trim();
|
|
166
|
+
//# sourceMappingURL=verification.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"verification.js","sourceRoot":"","sources":["../../src/lib/verification.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# Building on phygital assets
|
|
2
|
+
|
|
3
|
+
Third-party developers can:
|
|
4
|
+
|
|
5
|
+
- **Gate off-chain** by wallet holdings → `evaluateAssetGating`
|
|
6
|
+
- **Require live passkey presence on-chain** → composable `verify_asset` (two patterns below)
|
|
7
|
+
|
|
8
|
+
## Two on-chain composition patterns
|
|
9
|
+
|
|
10
|
+
Both start with the same client flow: `beginVerifyAsset` → NFC tap → `buildVerifyAssetArgs`.
|
|
11
|
+
|
|
12
|
+
### Pattern A — Client posts `verify_asset`, your program inspects
|
|
13
|
+
|
|
14
|
+
| Layer | Responsibility |
|
|
15
|
+
|-------|----------------|
|
|
16
|
+
| **Client** | `[secp256r1_verify, verify_asset, your_ix]` via `completeVerifyAsset` |
|
|
17
|
+
| **Your program** | Read instructions sysvar; find preceding `verify_asset`; verify `message` bytes |
|
|
18
|
+
|
|
19
|
+
Best when your program is a consumer of an already-executed proof. Reference: `phygital-spend`.
|
|
20
|
+
|
|
21
|
+
### Pattern B — Client posts `secp256r1_verify`, your program CPIs `verify_asset`
|
|
22
|
+
|
|
23
|
+
| Layer | Responsibility |
|
|
24
|
+
|-------|----------------|
|
|
25
|
+
| **Client** | `[secp256r1_verify, your_ix]` — pass `Secp256r1VerifyArgs` + `message` in your ix data |
|
|
26
|
+
| **Your program** | CPI `verify_asset` via `VerifyAssetCpiBuilder` (`phygital-token-client`) |
|
|
27
|
+
|
|
28
|
+
Best when your program orchestrates verification as part of its own instruction.
|
|
29
|
+
|
|
30
|
+
## Off-chain authentication (no `verify_asset`)
|
|
31
|
+
|
|
32
|
+
`verifyWithChallengeResponse` proves presence in the client only. It does **not** write to chain. Use for UI login when no program needs to inspect `verify_asset`.
|
|
33
|
+
|
|
34
|
+
## Message design checklist
|
|
35
|
+
|
|
36
|
+
- [ ] Define domain-separated `message` bytes (prefix + action fields)
|
|
37
|
+
- [ ] Same bytes in `beginVerifyAsset({ message })` and your program's check
|
|
38
|
+
- [ ] Never reuse messages across authorization scopes
|
|
39
|
+
|
|
40
|
+
## Crates
|
|
41
|
+
|
|
42
|
+
**TypeScript:** `phygital-token-sdk` — `buildVerifyAssetArgs`, `completeVerifyAsset`, `getVerifyAssetInstruction`
|
|
43
|
+
|
|
44
|
+
**Rust:** `phygital-token-client` at `clients/rust/phygital-token` — `VerifyAssetCpiBuilder`, `Secp256r1VerifyArgs`
|
|
45
|
+
|
|
46
|
+
See [rust-cpi.md](./rust-cpi.md).
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# Rust: building on `verify_asset`
|
|
2
|
+
|
|
3
|
+
Crate: `phygital-token-client` (`phygital_token_client`).
|
|
4
|
+
|
|
5
|
+
## Pattern A — Inspect prior `verify_asset` (phygital-spend)
|
|
6
|
+
|
|
7
|
+
Client sends `secp256r1_verify` + `verify_asset` + your instruction. Your program does **not** CPI.
|
|
8
|
+
|
|
9
|
+
1. Load `instructions_sysvar`
|
|
10
|
+
2. Scan instructions **before** your program's index
|
|
11
|
+
3. Find `phygital_token::verify_asset` for the expected `asset`
|
|
12
|
+
4. Decode instruction data; verify `message` matches your canonical payload
|
|
13
|
+
|
|
14
|
+
```rust
|
|
15
|
+
// Pseudocode — see phygital-spend require_matching_verify_asset
|
|
16
|
+
require!(decoded_message == expected_message, MyError::InvalidProof);
|
|
17
|
+
require!(verify_asset_asset == expected_asset, MyError::WrongAsset);
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## Pattern B — CPI `verify_asset` from your program
|
|
21
|
+
|
|
22
|
+
Client sends `secp256r1_verify` + your instruction (no client-side `verify_asset`). Your program CPIs:
|
|
23
|
+
|
|
24
|
+
```rust
|
|
25
|
+
use phygital_token_client::generated::instructions::VerifyAssetCpiBuilder;
|
|
26
|
+
use phygital_token_client::generated::types::Secp256r1VerifyArgs;
|
|
27
|
+
|
|
28
|
+
VerifyAssetCpiBuilder::new(phygital_token_program)
|
|
29
|
+
.asset(asset_account)
|
|
30
|
+
.slot_hashes(slot_hashes_sysvar)
|
|
31
|
+
.instructions_sysvar(instructions_sysvar)
|
|
32
|
+
.secp256r1_verify_args(secp256r1_verify_args)
|
|
33
|
+
.message(message_bytes)
|
|
34
|
+
.invoke()?;
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
The client obtains `secp256r1_verify_args` from TypeScript `buildVerifyAssetArgs` and passes them in your instruction data.
|
|
38
|
+
|
|
39
|
+
`secp256r1_verify` must appear earlier in the transaction (client includes it before your ix).
|
|
40
|
+
|
|
41
|
+
## `Secp256r1VerifyArgs`
|
|
42
|
+
|
|
43
|
+
```rust
|
|
44
|
+
pub struct Secp256r1VerifyArgs {
|
|
45
|
+
pub signed_message_index: u8,
|
|
46
|
+
pub slot_number: u64,
|
|
47
|
+
pub client_data_json: Vec<u8>,
|
|
48
|
+
}
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
Mirrors `buildVerifyAssetArgs` output in TypeScript.
|
|
52
|
+
|
|
53
|
+
## Testing
|
|
54
|
+
|
|
55
|
+
`programs/phygital-token/tests/verify_asset_flow.rs`
|
package/docs/glossary.md
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# Phygital Token — Domain Glossary
|
|
2
|
+
|
|
3
|
+
Shared vocabulary for on-chain accounts, instructions, tests, and the TypeScript client.
|
|
4
|
+
|
|
5
|
+
## Hierarchy
|
|
6
|
+
|
|
7
|
+
```
|
|
8
|
+
Collection (group_mint)
|
|
9
|
+
└── Design mint (mint) ← created by `create_mint`
|
|
10
|
+
└── Asset (asset PDA) ← created by `mint_token`, 1:1 with passkey
|
|
11
|
+
└── SPL token unit ← held in program_authority custody until claim
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
## Terms
|
|
15
|
+
|
|
16
|
+
| Term | On-chain / IDL name | Description |
|
|
17
|
+
|------|---------------------|-------------|
|
|
18
|
+
| **Collection** | `group_mint` | Token-2022 TokenGroup parent mint. Groups related designs. |
|
|
19
|
+
| **Design** | `mint` (in `create_mint`) | Shared SFT template — one metadata set, many physical instances. |
|
|
20
|
+
| **Asset** | `asset` account | Per-physical-item record keyed by secp256r1 passkey pubkey. |
|
|
21
|
+
| **Owner** | `asset.owner` | Current custodian after a successful `execute_transfer` claim. |
|
|
22
|
+
| **Custody** | `program_authority` | PDA that holds unclaimed tokens and acts as permanent delegate. |
|
|
23
|
+
|
|
24
|
+
## Instruction map
|
|
25
|
+
|
|
26
|
+
| Instruction | What it does |
|
|
27
|
+
|-------------|--------------|
|
|
28
|
+
| `create_mint` | Creates a **design** mint (member of a collection `group_mint`). |
|
|
29
|
+
| `mint_token` | Mints one SPL token into custody and initializes an **asset** PDA. |
|
|
30
|
+
| `execute_transfer` | Passkey-authorized claim/transfer from current owner to recipient. |
|
|
31
|
+
| `set_lock_state` | Owner toggles transfer lock on a configurable asset. |
|
|
32
|
+
| `create_domain_config` / `update_domain_config` | WebAuthn RP ID and origin allowlist. |
|
|
33
|
+
|
|
34
|
+
## Client naming
|
|
35
|
+
|
|
36
|
+
| Rust / IDL | TypeScript (hand-written) |
|
|
37
|
+
|------------|---------------------------|
|
|
38
|
+
| `group_mint` | `groupMint` / `collectionMint` (display) |
|
|
39
|
+
| `create_mint` | `buildCreateMintInstructions` |
|
|
40
|
+
| `mint_token` | `buildMintTokenInstructions` |
|
|
41
|
+
| `asset` PDA | `findAssetPda`, `AssetDisplayInfo` |
|
|
42
|
+
|
|
43
|
+
Test helpers mirror on-chain instruction names (`create_mint`, `mint_token`, etc.).
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
# SDK surface area
|
|
2
|
+
|
|
3
|
+
TypeScript package: `phygital-token-sdk` (`clients/js/phygital-token`).
|
|
4
|
+
|
|
5
|
+
## Mint
|
|
6
|
+
|
|
7
|
+
| Export | Purpose |
|
|
8
|
+
|--------|---------|
|
|
9
|
+
| `buildCreateMintInstructions` | Create design mint in a collection |
|
|
10
|
+
| `buildMintTokenInstructions` | Mint token + initialize asset PDA |
|
|
11
|
+
| `parseSecp256r1Pubkey` | Parse base64url compressed P-256 key |
|
|
12
|
+
| `parseCredentialId` | Parse base64url credential id |
|
|
13
|
+
| `validateMetadataFields` | Name/symbol/uri length checks |
|
|
14
|
+
|
|
15
|
+
## Transfer
|
|
16
|
+
|
|
17
|
+
| Export | Purpose |
|
|
18
|
+
|--------|---------|
|
|
19
|
+
| `beginTransfer` | Slot-bound transfer challenge |
|
|
20
|
+
| `authenticatePasskeyForTransfer` | WebAuthn NFC tap |
|
|
21
|
+
| `completeTransfer` | `secp256r1_verify` + `execute_transfer` |
|
|
22
|
+
|
|
23
|
+
## Verify asset (composable)
|
|
24
|
+
|
|
25
|
+
| Export | Purpose |
|
|
26
|
+
|--------|---------|
|
|
27
|
+
| `beginVerifyAsset` | Slot-bound verify challenge for custom `message` |
|
|
28
|
+
| `authenticatePasskeyForVerifyAsset` | WebAuthn NFC tap |
|
|
29
|
+
| `buildVerifyAssetArgs` | Build secp256r1 + resolve asset after tap |
|
|
30
|
+
| `completeVerifyAsset` | Full instruction pair |
|
|
31
|
+
|
|
32
|
+
## Verification (client helpers — off-chain only)
|
|
33
|
+
|
|
34
|
+
| Export | Purpose |
|
|
35
|
+
|--------|---------|
|
|
36
|
+
| `verifyDynamicUrl` | Identification via signed URL (server) |
|
|
37
|
+
| `verifyDynamicUrlWithoutCounterCheck` | Identification offline |
|
|
38
|
+
| `verifyWithChallengeResponse` | Off-chain authentication (browser); does not submit `verify_asset` |
|
|
39
|
+
| `verifyWithChallengeResponseOverNfc` | Off-chain authentication (native NFC) |
|
|
40
|
+
|
|
41
|
+
On-chain proof always uses `beginVerifyAsset` / `buildVerifyAssetArgs` / `completeVerifyAsset`.
|
|
42
|
+
|
|
43
|
+
## Asset lookup & metadata
|
|
44
|
+
|
|
45
|
+
| Export | Purpose |
|
|
46
|
+
|--------|---------|
|
|
47
|
+
| `findAssetPda` | Derive asset PDA from secp256r1 pubkey |
|
|
48
|
+
| `fetchAssetFromCredentialId` | Resolve asset + pubkey from credential |
|
|
49
|
+
| `fetchAllAssetsFromOwner` | List assets by wallet owner |
|
|
50
|
+
| `fetchAssetDisplayInfo` | Rich display metadata |
|
|
51
|
+
| `resolveMedia` | Resolve media URLs from token metadata |
|
|
52
|
+
|
|
53
|
+
## Gating
|
|
54
|
+
|
|
55
|
+
| Export | Purpose |
|
|
56
|
+
|--------|---------|
|
|
57
|
+
| `evaluateAssetGating` | Full tier evaluation for asset owner wallet |
|
|
58
|
+
| `evaluateGatingTiers` / `evaluateGatingFilter` | Lower-level evaluators |
|
|
59
|
+
| `Gating` / `GatingTraitValue` | Filter builders |
|
|
60
|
+
| `summarizeGatingEvaluationFailure` | Human-readable failure reasons |
|
|
61
|
+
|
|
62
|
+
## Generated (Codama)
|
|
63
|
+
|
|
64
|
+
Re-exported from `./generated/index.js`:
|
|
65
|
+
|
|
66
|
+
- Instructions: `getCreateMintInstructionAsync`, `getMintTokenInstructionAsync`, `getExecuteTransferInstructionAsync`, `getVerifyAssetInstruction`, `getSetLockStateInstruction`, ...
|
|
67
|
+
- Accounts: `fetchAsset`, `Asset`, ...
|
|
68
|
+
- Types: `AssetType`, `Secp256r1VerifyArgs`, `CredentialId`, ...
|
|
69
|
+
- PDAs: `findProgramAuthorityPda`, ...
|
|
70
|
+
|
|
71
|
+
## Rust client
|
|
72
|
+
|
|
73
|
+
Crate: `phygital-token-client` at `clients/rust/phygital-token`.
|
|
74
|
+
|
|
75
|
+
On-chain: instruction builders, CPI helpers, account layouts, errors.
|
|
76
|
+
|
|
77
|
+
Off-chain (`fetch` feature): RPC account fetching helpers.
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
# Verification methods (`verify.ts`)
|
|
2
|
+
|
|
3
|
+
All exports from `clients/js/phygital-token/src/utils/verify.ts`.
|
|
4
|
+
|
|
5
|
+
## Identification (no second tap)
|
|
6
|
+
|
|
7
|
+
### `verifyDynamicUrl(params, callback?)`
|
|
8
|
+
|
|
9
|
+
**Use when:** User already tapped once; you have signed URL query params (`pk`, `s`, `c`, `n`).
|
|
10
|
+
|
|
11
|
+
### `verifyDynamicUrlWithoutCounterCheck(params)`
|
|
12
|
+
|
|
13
|
+
**Use when:** Offline device, no verification server. Copied links can be replayed.
|
|
14
|
+
|
|
15
|
+
## Authentication — off-chain only (live tap)
|
|
16
|
+
|
|
17
|
+
### `verifyWithChallengeResponse({ rpc, message?, fetchPublicKeyFromCredentialIdCallback? })`
|
|
18
|
+
|
|
19
|
+
**Use when:** Browser web app; prove holder is present **without** an on-chain transaction.
|
|
20
|
+
|
|
21
|
+
Optional `message` sets the WebAuthn challenge (UTF-8 encoded). When omitted, a random 32-byte challenge is used. This lets you bind the tap to app-specific context (e.g. session id, action label) without going on-chain.
|
|
22
|
+
|
|
23
|
+
```ts
|
|
24
|
+
// Random challenge
|
|
25
|
+
await verifyWithChallengeResponse({ rpc });
|
|
26
|
+
|
|
27
|
+
// Bound challenge (still off-chain)
|
|
28
|
+
await verifyWithChallengeResponse({
|
|
29
|
+
rpc,
|
|
30
|
+
message: `login:${sessionId}`,
|
|
31
|
+
});
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
Returns `{ publicKey, isVerified }`. Does **not** submit `verify_asset`.
|
|
35
|
+
|
|
36
|
+
For on-chain proof with a bound message, use `beginVerifyAsset({ message: Uint8Array })` instead.
|
|
37
|
+
|
|
38
|
+
### `verifyWithChallengeResponseOverNfc({ rpc, message?, transceive, ... })`
|
|
39
|
+
|
|
40
|
+
Same as above for React Native / native NFC apps. Optional `message` binds the challenge the same way.
|
|
41
|
+
|
|
42
|
+
## Off-chain auth vs on-chain composable
|
|
43
|
+
|
|
44
|
+
| Need | Use |
|
|
45
|
+
|------|-----|
|
|
46
|
+
| UI login, bound or random challenge, no tx | `verifyWithChallengeResponse({ message? })` |
|
|
47
|
+
| On-chain proof — Pattern A | `completeVerifyAsset` + your ix |
|
|
48
|
+
| On-chain proof — Pattern B | `buildVerifyAssetArgs` + your ix |
|
|
49
|
+
| Transfer ownership | `beginTransfer` → `completeTransfer` |
|
|
50
|
+
|
|
51
|
+
## Message: off-chain vs on-chain
|
|
52
|
+
|
|
53
|
+
| Context | `message` type | Effect |
|
|
54
|
+
|---------|----------------|--------|
|
|
55
|
+
| `verifyWithChallengeResponse` | optional `string` | WebAuthn challenge bytes (UTF-8) |
|
|
56
|
+
| `beginVerifyAsset` | `Uint8Array` | Hashed into slot-bound on-chain challenge |
|
|
57
|
+
|
|
58
|
+
An off-chain `message` in `verifyWithChallengeResponse` does **not** produce an on-chain `verify_asset` record. Use the composable flow when your program must inspect or CPI `verify_asset`.
|