phygital-token-sdk 0.5.3 → 0.6.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 +94 -0
- package/dist/index.d.ts +6 -8
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -8
- package/dist/index.js.map +1 -1
- package/dist/instructions/transfer.d.ts +3 -9
- package/dist/instructions/transfer.d.ts.map +1 -1
- package/dist/instructions/transfer.js +7 -28
- package/dist/instructions/transfer.js.map +1 -1
- package/dist/instructions/verifyAsset.d.ts +14 -9
- package/dist/instructions/verifyAsset.d.ts.map +1 -1
- package/dist/instructions/verifyAsset.js +44 -19
- package/dist/instructions/verifyAsset.js.map +1 -1
- package/dist/utils/assetCredential.d.ts +1 -1
- package/dist/utils/assetCredential.d.ts.map +1 -1
- package/dist/utils/assetCredential.js +2 -2
- package/dist/utils/assetCredential.js.map +1 -1
- package/dist/utils/consts.d.ts +1 -1
- package/dist/utils/consts.d.ts.map +1 -1
- package/dist/utils/consts.js +1 -1
- package/dist/utils/consts.js.map +1 -1
- package/dist/utils/gating.d.ts +195 -0
- package/dist/utils/gating.d.ts.map +1 -0
- package/dist/utils/gating.js +481 -0
- package/dist/utils/gating.js.map +1 -0
- package/dist/utils/passkey/nfc/authDataExtensions.d.ts.map +1 -1
- package/dist/utils/passkey/nfc/authDataExtensions.js +2 -2
- package/dist/utils/passkey/nfc/authDataExtensions.js.map +1 -1
- package/dist/utils/passkey/secp256r1.d.ts +8 -5
- package/dist/utils/passkey/secp256r1.d.ts.map +1 -1
- package/dist/utils/passkey/secp256r1.js +14 -23
- package/dist/utils/passkey/secp256r1.js.map +1 -1
- package/dist/utils/slotHash.d.ts +1 -2
- package/dist/utils/slotHash.d.ts.map +1 -1
- package/dist/utils/slotHash.js +0 -12
- package/dist/utils/slotHash.js.map +1 -1
- package/dist/utils/verify.d.ts +2 -9
- package/dist/utils/verify.d.ts.map +1 -1
- package/dist/utils/verify.js +12 -104
- package/dist/utils/verify.js.map +1 -1
- package/docs/gating/README.md +83 -0
- package/docs/gating/evaluation-and-errors.md +134 -0
- package/docs/gating/filters-and-composition.md +120 -0
- package/docs/gating/overview.md +84 -0
- package/docs/gating/predicates.md +122 -0
- package/docs/gating/recipes.md +199 -0
- package/docs/gating/tiers.md +158 -0
- package/package.json +11 -10
- package/dist/__tests__/card-instance.test.d.ts +0 -2
- package/dist/__tests__/card-instance.test.d.ts.map +0 -1
- package/dist/__tests__/card-instance.test.js +0 -38
- package/dist/__tests__/card-instance.test.js.map +0 -1
- package/dist/__tests__/crypto-parity.test.d.ts +0 -2
- package/dist/__tests__/crypto-parity.test.d.ts.map +0 -1
- package/dist/__tests__/crypto-parity.test.js +0 -60
- package/dist/__tests__/crypto-parity.test.js.map +0 -1
- package/dist/__tests__/low-s-normalization.test.d.ts +0 -2
- package/dist/__tests__/low-s-normalization.test.d.ts.map +0 -1
- package/dist/__tests__/low-s-normalization.test.js +0 -44
- package/dist/__tests__/low-s-normalization.test.js.map +0 -1
- package/dist/__tests__/metadata-limits.test.d.ts +0 -2
- package/dist/__tests__/metadata-limits.test.d.ts.map +0 -1
- package/dist/__tests__/metadata-limits.test.js +0 -33
- package/dist/__tests__/metadata-limits.test.js.map +0 -1
- package/dist/__tests__/nfc-cbor.test.d.ts +0 -2
- package/dist/__tests__/nfc-cbor.test.d.ts.map +0 -1
- package/dist/__tests__/nfc-cbor.test.js +0 -72
- package/dist/__tests__/nfc-cbor.test.js.map +0 -1
- package/dist/consts.d.ts +0 -19
- package/dist/consts.d.ts.map +0 -1
- package/dist/consts.js +0 -19
- package/dist/consts.js.map +0 -1
- package/dist/generated/accounts/cardInstance.d.ts +0 -35
- package/dist/generated/accounts/cardInstance.d.ts.map +0 -1
- package/dist/generated/accounts/cardInstance.js +0 -61
- package/dist/generated/accounts/cardInstance.js.map +0 -1
- package/dist/generated/accounts/domainConfig.d.ts +0 -28
- package/dist/generated/accounts/domainConfig.d.ts.map +0 -1
- package/dist/generated/accounts/domainConfig.js +0 -58
- package/dist/generated/accounts/domainConfig.js.map +0 -1
- package/dist/generated/errors/phygitalNfts.d.ts +0 -62
- package/dist/generated/errors/phygitalNfts.d.ts.map +0 -1
- package/dist/generated/errors/phygitalNfts.js +0 -87
- package/dist/generated/errors/phygitalNfts.js.map +0 -1
- package/dist/generated/instructions/createCollectionMint.d.ts +0 -108
- package/dist/generated/instructions/createCollectionMint.d.ts.map +0 -1
- package/dist/generated/instructions/createCollectionMint.js +0 -175
- package/dist/generated/instructions/createCollectionMint.js.map +0 -1
- package/dist/generated/instructions/createDesignMint.d.ts +0 -97
- package/dist/generated/instructions/createDesignMint.d.ts.map +0 -1
- package/dist/generated/instructions/createDesignMint.js +0 -164
- package/dist/generated/instructions/createDesignMint.js.map +0 -1
- package/dist/generated/instructions/createDomainConfig.d.ts +0 -46
- package/dist/generated/instructions/createDomainConfig.d.ts.map +0 -1
- package/dist/generated/instructions/createDomainConfig.js +0 -83
- package/dist/generated/instructions/createDomainConfig.js.map +0 -1
- package/dist/generated/instructions/createGroupToken.d.ts +0 -94
- package/dist/generated/instructions/createGroupToken.d.ts.map +0 -1
- package/dist/generated/instructions/createGroupToken.js +0 -150
- package/dist/generated/instructions/createGroupToken.js.map +0 -1
- package/dist/generated/instructions/createToken.d.ts +0 -88
- package/dist/generated/instructions/createToken.d.ts.map +0 -1
- package/dist/generated/instructions/createToken.js +0 -182
- package/dist/generated/instructions/createToken.js.map +0 -1
- package/dist/generated/instructions/editDomainConfig.d.ts +0 -50
- package/dist/generated/instructions/editDomainConfig.d.ts.map +0 -1
- package/dist/generated/instructions/editDomainConfig.js +0 -90
- package/dist/generated/instructions/editDomainConfig.js.map +0 -1
- package/dist/generated/instructions/executeSpend.d.ts +0 -86
- package/dist/generated/instructions/executeSpend.d.ts.map +0 -1
- package/dist/generated/instructions/executeSpend.js +0 -187
- package/dist/generated/instructions/executeSpend.js.map +0 -1
- package/dist/generated/instructions/setTransferConfig.d.ts +0 -88
- package/dist/generated/instructions/setTransferConfig.d.ts.map +0 -1
- package/dist/generated/instructions/setTransferConfig.js +0 -188
- package/dist/generated/instructions/setTransferConfig.js.map +0 -1
- package/dist/generated/instructions/updateCounter.d.ts +0 -45
- package/dist/generated/instructions/updateCounter.d.ts.map +0 -1
- package/dist/generated/instructions/updateCounter.js +0 -84
- package/dist/generated/instructions/updateCounter.js.map +0 -1
- package/dist/generated/instructions/updateDomainConfig.d.ts +0 -43
- package/dist/generated/instructions/updateDomainConfig.d.ts.map +0 -1
- package/dist/generated/instructions/updateDomainConfig.js +0 -81
- package/dist/generated/instructions/updateDomainConfig.js.map +0 -1
- package/dist/generated/pdas/spendAuthority.d.ts +0 -8
- package/dist/generated/pdas/spendAuthority.d.ts.map +0 -1
- package/dist/generated/pdas/spendAuthority.js +0 -15
- package/dist/generated/pdas/spendAuthority.js.map +0 -1
- package/dist/generated/programs/phygitalNfts.d.ts +0 -72
- package/dist/generated/programs/phygitalNfts.d.ts.map +0 -1
- package/dist/generated/programs/phygitalNfts.js +0 -136
- package/dist/generated/programs/phygitalNfts.js.map +0 -1
- package/dist/instructions/collection.d.ts +0 -14
- package/dist/instructions/collection.d.ts.map +0 -1
- package/dist/instructions/collection.js +0 -59
- package/dist/instructions/collection.js.map +0 -1
- package/dist/instructions/index.d.ts +0 -2
- package/dist/instructions/index.d.ts.map +0 -1
- package/dist/instructions/index.js +0 -2
- package/dist/instructions/index.js.map +0 -1
- package/dist/instructions/secp256r1Verify.d.ts +0 -29
- package/dist/instructions/secp256r1Verify.d.ts.map +0 -1
- package/dist/instructions/secp256r1Verify.js +0 -132
- package/dist/instructions/secp256r1Verify.js.map +0 -1
- package/dist/instructions/setLockState.d.ts +0 -19
- package/dist/instructions/setLockState.d.ts.map +0 -1
- package/dist/instructions/setLockState.js +0 -17
- package/dist/instructions/setLockState.js.map +0 -1
- package/dist/instructions/setTransferConfig.d.ts +0 -25
- package/dist/instructions/setTransferConfig.d.ts.map +0 -1
- package/dist/instructions/setTransferConfig.js +0 -20
- package/dist/instructions/setTransferConfig.js.map +0 -1
- package/dist/instructions/updateCounter.d.ts +0 -15
- package/dist/instructions/updateCounter.d.ts.map +0 -1
- package/dist/instructions/updateCounter.js +0 -20
- package/dist/instructions/updateCounter.js.map +0 -1
- package/dist/mint-metadata.d.ts +0 -13
- package/dist/mint-metadata.d.ts.map +0 -1
- package/dist/mint-metadata.js +0 -127
- package/dist/mint-metadata.js.map +0 -1
- package/dist/passkeys/index.d.ts +0 -18
- package/dist/passkeys/index.d.ts.map +0 -1
- package/dist/passkeys/index.js +0 -30
- package/dist/passkeys/index.js.map +0 -1
- package/dist/passkeys/internal.d.ts +0 -15
- package/dist/passkeys/internal.d.ts.map +0 -1
- package/dist/passkeys/internal.js +0 -113
- package/dist/passkeys/internal.js.map +0 -1
- package/dist/secp256r1.d.ts +0 -24
- package/dist/secp256r1.d.ts.map +0 -1
- package/dist/secp256r1.js +0 -38
- package/dist/secp256r1.js.map +0 -1
- package/dist/transfer.d.ts +0 -28
- package/dist/transfer.d.ts.map +0 -1
- package/dist/transfer.js +0 -109
- package/dist/transfer.js.map +0 -1
- package/dist/utils/encoding.d.ts +0 -3
- package/dist/utils/encoding.d.ts.map +0 -1
- package/dist/utils/encoding.js +0 -14
- package/dist/utils/encoding.js.map +0 -1
- package/dist/utils/passkey/index.d.ts +0 -17
- package/dist/utils/passkey/index.d.ts.map +0 -1
- package/dist/utils/passkey/index.js +0 -21
- package/dist/utils/passkey/index.js.map +0 -1
- package/dist/utils/passkey/nfc/base64url.d.ts +0 -2
- package/dist/utils/passkey/nfc/base64url.d.ts.map +0 -1
- package/dist/utils/passkey/nfc/base64url.js +0 -13
- package/dist/utils/passkey/nfc/base64url.js.map +0 -1
- package/dist/utils/pdas/domainConfig.d.ts +0 -3
- package/dist/utils/pdas/domainConfig.d.ts.map +0 -1
- package/dist/utils/pdas/domainConfig.js +0 -15
- package/dist/utils/pdas/domainConfig.js.map +0 -1
- package/dist/utils/sendInstructions.d.ts +0 -7
- package/dist/utils/sendInstructions.d.ts.map +0 -1
- package/dist/utils/sendInstructions.js +0 -13
- package/dist/utils/sendInstructions.js.map +0 -1
- package/dist/utils/tokenOwner.d.ts +0 -7
- package/dist/utils/tokenOwner.d.ts.map +0 -1
- package/dist/utils/tokenOwner.js +0 -24
- package/dist/utils/tokenOwner.js.map +0 -1
- package/dist/utils.d.ts +0 -10
- package/dist/utils.d.ts.map +0 -1
- package/dist/utils.js +0 -42
- package/dist/utils.js.map +0 -1
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
import type { Address, Rpc, SolanaRpcApi } from "@solana/kit";
|
|
2
|
+
type DasAssetAttribute = {
|
|
3
|
+
trait_type?: string;
|
|
4
|
+
value?: string | number;
|
|
5
|
+
};
|
|
6
|
+
type DasAsset = {
|
|
7
|
+
id: string;
|
|
8
|
+
grouping?: Array<[string, string] | {
|
|
9
|
+
group_key: string;
|
|
10
|
+
group_value: string;
|
|
11
|
+
}>;
|
|
12
|
+
token_info?: {
|
|
13
|
+
balance?: number;
|
|
14
|
+
decimals?: number;
|
|
15
|
+
};
|
|
16
|
+
content?: {
|
|
17
|
+
metadata?: {
|
|
18
|
+
attributes?: DasAssetAttribute[];
|
|
19
|
+
};
|
|
20
|
+
};
|
|
21
|
+
};
|
|
22
|
+
type GatingStringOp = {
|
|
23
|
+
op: "eq";
|
|
24
|
+
value: string;
|
|
25
|
+
} | {
|
|
26
|
+
op: "neq";
|
|
27
|
+
value: string;
|
|
28
|
+
} | {
|
|
29
|
+
op: "in";
|
|
30
|
+
values: readonly string[];
|
|
31
|
+
} | {
|
|
32
|
+
op: "notIn";
|
|
33
|
+
values: readonly string[];
|
|
34
|
+
};
|
|
35
|
+
type GatingTraitOp = {
|
|
36
|
+
op: "eq";
|
|
37
|
+
value: string | number;
|
|
38
|
+
} | {
|
|
39
|
+
op: "neq";
|
|
40
|
+
value: string | number;
|
|
41
|
+
} | {
|
|
42
|
+
op: "in";
|
|
43
|
+
values: readonly (string | number)[];
|
|
44
|
+
} | {
|
|
45
|
+
op: "notIn";
|
|
46
|
+
values: readonly (string | number)[];
|
|
47
|
+
} | {
|
|
48
|
+
op: "gte";
|
|
49
|
+
value: number;
|
|
50
|
+
} | {
|
|
51
|
+
op: "lte";
|
|
52
|
+
value: number;
|
|
53
|
+
} | {
|
|
54
|
+
op: "between";
|
|
55
|
+
min: number;
|
|
56
|
+
max: number;
|
|
57
|
+
};
|
|
58
|
+
type GatingTrait = {
|
|
59
|
+
trait_type: string;
|
|
60
|
+
} & GatingTraitOp;
|
|
61
|
+
type GatingTraits = {
|
|
62
|
+
all: readonly GatingTrait[];
|
|
63
|
+
} | {
|
|
64
|
+
any: readonly GatingTrait[];
|
|
65
|
+
};
|
|
66
|
+
type GatingBalance = {
|
|
67
|
+
min?: bigint;
|
|
68
|
+
max?: bigint;
|
|
69
|
+
};
|
|
70
|
+
export type GatingAssetPredicate = {
|
|
71
|
+
collection?: GatingStringOp;
|
|
72
|
+
mint?: GatingStringOp;
|
|
73
|
+
traits?: GatingTraits;
|
|
74
|
+
balance?: GatingBalance;
|
|
75
|
+
};
|
|
76
|
+
export type GatingFilter = {
|
|
77
|
+
count: {
|
|
78
|
+
min: number;
|
|
79
|
+
max?: number;
|
|
80
|
+
match: GatingAssetPredicate;
|
|
81
|
+
};
|
|
82
|
+
} | {
|
|
83
|
+
totalBalance: {
|
|
84
|
+
mint: string;
|
|
85
|
+
min?: bigint;
|
|
86
|
+
max?: bigint;
|
|
87
|
+
};
|
|
88
|
+
} | {
|
|
89
|
+
and: GatingFilter[];
|
|
90
|
+
} | {
|
|
91
|
+
or: GatingFilter[];
|
|
92
|
+
} | {
|
|
93
|
+
not: GatingFilter;
|
|
94
|
+
};
|
|
95
|
+
export type GatingFilterResult = {
|
|
96
|
+
kind: "count";
|
|
97
|
+
filter: {
|
|
98
|
+
count: {
|
|
99
|
+
min: number;
|
|
100
|
+
max?: number;
|
|
101
|
+
match: GatingAssetPredicate;
|
|
102
|
+
};
|
|
103
|
+
};
|
|
104
|
+
passed: boolean;
|
|
105
|
+
matchCount: number;
|
|
106
|
+
} | {
|
|
107
|
+
kind: "totalBalance";
|
|
108
|
+
filter: {
|
|
109
|
+
totalBalance: {
|
|
110
|
+
mint: string;
|
|
111
|
+
min?: bigint;
|
|
112
|
+
max?: bigint;
|
|
113
|
+
};
|
|
114
|
+
};
|
|
115
|
+
passed: boolean;
|
|
116
|
+
total: bigint;
|
|
117
|
+
} | {
|
|
118
|
+
kind: "and";
|
|
119
|
+
filter: {
|
|
120
|
+
and: GatingFilter[];
|
|
121
|
+
};
|
|
122
|
+
passed: boolean;
|
|
123
|
+
children: GatingFilterResult[];
|
|
124
|
+
} | {
|
|
125
|
+
kind: "or";
|
|
126
|
+
filter: {
|
|
127
|
+
or: GatingFilter[];
|
|
128
|
+
};
|
|
129
|
+
passed: boolean;
|
|
130
|
+
children: GatingFilterResult[];
|
|
131
|
+
} | {
|
|
132
|
+
kind: "not";
|
|
133
|
+
filter: {
|
|
134
|
+
not: GatingFilter;
|
|
135
|
+
};
|
|
136
|
+
passed: boolean;
|
|
137
|
+
child: GatingFilterResult;
|
|
138
|
+
};
|
|
139
|
+
export type GatingTier<TId extends string = string> = {
|
|
140
|
+
id: TId;
|
|
141
|
+
filter: GatingFilter;
|
|
142
|
+
};
|
|
143
|
+
export type GatingTierEvaluationResult<TId extends string = string> = {
|
|
144
|
+
id: TId;
|
|
145
|
+
passed: boolean;
|
|
146
|
+
filterResult: GatingFilterResult;
|
|
147
|
+
};
|
|
148
|
+
export type GatingTiersEvaluationResult<TId extends string = string> = {
|
|
149
|
+
tiers: GatingTierEvaluationResult<TId>[];
|
|
150
|
+
passedTierIds: TId[];
|
|
151
|
+
passed: boolean;
|
|
152
|
+
};
|
|
153
|
+
export type GatingEvaluationResult<TId extends string = string> = GatingTiersEvaluationResult<TId> & {
|
|
154
|
+
owner: Address;
|
|
155
|
+
};
|
|
156
|
+
export type EvaluateAssetGatingOptions<TId extends string = string> = {
|
|
157
|
+
assetPublicKey: string;
|
|
158
|
+
rpc: Rpc<SolanaRpcApi>;
|
|
159
|
+
tiers: readonly GatingTier<TId>[];
|
|
160
|
+
};
|
|
161
|
+
export declare const Gating: {
|
|
162
|
+
readonly and: (...filters: GatingFilter[]) => GatingFilter;
|
|
163
|
+
readonly or: (...filters: GatingFilter[]) => GatingFilter;
|
|
164
|
+
readonly not: (filter: GatingFilter) => GatingFilter;
|
|
165
|
+
readonly tier: <TId extends string>(id: TId, filter: GatingFilter) => GatingTier<TId>;
|
|
166
|
+
readonly count: (min: number, match: GatingAssetPredicate, max?: number) => GatingFilter;
|
|
167
|
+
readonly totalBalance: (mint: string, min?: bigint, max?: bigint) => GatingFilter;
|
|
168
|
+
readonly eq: (value: string) => GatingStringOp;
|
|
169
|
+
readonly neq: (value: string) => GatingStringOp;
|
|
170
|
+
readonly in: (...values: string[]) => GatingStringOp;
|
|
171
|
+
readonly notIn: (...values: string[]) => GatingStringOp;
|
|
172
|
+
readonly trait: (trait_type: string, op: GatingTraitOp) => GatingTrait;
|
|
173
|
+
readonly traitsAll: (...traits: GatingTrait[]) => GatingTraits;
|
|
174
|
+
readonly traitsAny: (...traits: GatingTrait[]) => GatingTraits;
|
|
175
|
+
readonly balance: (min?: bigint, max?: bigint) => GatingBalance;
|
|
176
|
+
};
|
|
177
|
+
export declare const GatingTraitValue: {
|
|
178
|
+
readonly eq: (value: string | number) => GatingTraitOp;
|
|
179
|
+
readonly neq: (value: string | number) => GatingTraitOp;
|
|
180
|
+
readonly in: (...values: (string | number)[]) => GatingTraitOp;
|
|
181
|
+
readonly notIn: (...values: (string | number)[]) => GatingTraitOp;
|
|
182
|
+
readonly gte: (value: number) => GatingTraitOp;
|
|
183
|
+
readonly lte: (value: number) => GatingTraitOp;
|
|
184
|
+
readonly between: (min: number, max: number) => GatingTraitOp;
|
|
185
|
+
};
|
|
186
|
+
export declare function assetMatchesPredicate(asset: DasAsset, predicate: GatingAssetPredicate): boolean;
|
|
187
|
+
export declare function evaluateGatingFilter(assets: DasAsset[], filter: GatingFilter): GatingFilterResult;
|
|
188
|
+
export declare function formatGatingPredicate(predicate: GatingAssetPredicate): string;
|
|
189
|
+
export declare function summarizeGatingFailure(result: GatingFilterResult): string[];
|
|
190
|
+
export declare function summarizeGatingTierFailure(tier: GatingTierEvaluationResult): string[];
|
|
191
|
+
export declare function summarizeGatingEvaluationFailure<TId extends string>(result: GatingTiersEvaluationResult<TId> | GatingEvaluationResult<TId>): string[];
|
|
192
|
+
export declare function evaluateGatingTiers<TId extends string>(assets: DasAsset[], tiers: readonly GatingTier<TId>[]): GatingTiersEvaluationResult<TId>;
|
|
193
|
+
export declare function evaluateAssetGating<TId extends string>(options: EvaluateAssetGatingOptions<TId>): Promise<GatingEvaluationResult<TId>>;
|
|
194
|
+
export {};
|
|
195
|
+
//# sourceMappingURL=gating.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gating.d.ts","sourceRoot":"","sources":["../../src/utils/gating.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,481 @@
|
|
|
1
|
+
import { fetchAsset } from "../generated/index.js";
|
|
2
|
+
import { parseSecp256r1Pubkey } from "../instructions/mint.js";
|
|
3
|
+
import { findAssetPda } from "./pdas/asset.js";
|
|
4
|
+
export const Gating = {
|
|
5
|
+
and(...filters) {
|
|
6
|
+
return { and: filters };
|
|
7
|
+
},
|
|
8
|
+
or(...filters) {
|
|
9
|
+
return { or: filters };
|
|
10
|
+
},
|
|
11
|
+
not(filter) {
|
|
12
|
+
return { not: filter };
|
|
13
|
+
},
|
|
14
|
+
tier(id, filter) {
|
|
15
|
+
return { id, filter };
|
|
16
|
+
},
|
|
17
|
+
count(min, match, max) {
|
|
18
|
+
return { count: { min, max, match } };
|
|
19
|
+
},
|
|
20
|
+
totalBalance(mint, min, max) {
|
|
21
|
+
return { totalBalance: { mint, min, max } };
|
|
22
|
+
},
|
|
23
|
+
eq(value) {
|
|
24
|
+
return { op: "eq", value };
|
|
25
|
+
},
|
|
26
|
+
neq(value) {
|
|
27
|
+
return { op: "neq", value };
|
|
28
|
+
},
|
|
29
|
+
in(...values) {
|
|
30
|
+
return { op: "in", values };
|
|
31
|
+
},
|
|
32
|
+
notIn(...values) {
|
|
33
|
+
return { op: "notIn", values };
|
|
34
|
+
},
|
|
35
|
+
trait(trait_type, op) {
|
|
36
|
+
return { trait_type, ...op };
|
|
37
|
+
},
|
|
38
|
+
traitsAll(...traits) {
|
|
39
|
+
return { all: traits };
|
|
40
|
+
},
|
|
41
|
+
traitsAny(...traits) {
|
|
42
|
+
return { any: traits };
|
|
43
|
+
},
|
|
44
|
+
balance(min, max) {
|
|
45
|
+
return { min, max };
|
|
46
|
+
},
|
|
47
|
+
};
|
|
48
|
+
export const GatingTraitValue = {
|
|
49
|
+
eq(value) {
|
|
50
|
+
return { op: "eq", value };
|
|
51
|
+
},
|
|
52
|
+
neq(value) {
|
|
53
|
+
return { op: "neq", value };
|
|
54
|
+
},
|
|
55
|
+
in(...values) {
|
|
56
|
+
return { op: "in", values };
|
|
57
|
+
},
|
|
58
|
+
notIn(...values) {
|
|
59
|
+
return { op: "notIn", values };
|
|
60
|
+
},
|
|
61
|
+
gte(value) {
|
|
62
|
+
return { op: "gte", value };
|
|
63
|
+
},
|
|
64
|
+
lte(value) {
|
|
65
|
+
return { op: "lte", value };
|
|
66
|
+
},
|
|
67
|
+
between(min, max) {
|
|
68
|
+
return { op: "between", min, max };
|
|
69
|
+
},
|
|
70
|
+
};
|
|
71
|
+
async function fetchAssetOwner(rpc, assetPublicKey) {
|
|
72
|
+
const assetPda = await findAssetPda(parseSecp256r1Pubkey(assetPublicKey));
|
|
73
|
+
const account = await fetchAsset(rpc, assetPda);
|
|
74
|
+
return account.data.owner;
|
|
75
|
+
}
|
|
76
|
+
function createSearchAssetsClient(rpc) {
|
|
77
|
+
return async (params) => {
|
|
78
|
+
const rpcWithExecute = rpc;
|
|
79
|
+
return rpcWithExecute
|
|
80
|
+
.execute({ methodName: "searchAssets", params })
|
|
81
|
+
.send();
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
async function fetchOwnerDasAssets(owner, rpc) {
|
|
85
|
+
const searchAssets = createSearchAssetsClient(rpc);
|
|
86
|
+
const pageSize = 1000;
|
|
87
|
+
const items = [];
|
|
88
|
+
let page = 1;
|
|
89
|
+
while (true) {
|
|
90
|
+
const result = await searchAssets({
|
|
91
|
+
ownerAddress: owner,
|
|
92
|
+
tokenType: "all",
|
|
93
|
+
page,
|
|
94
|
+
limit: pageSize,
|
|
95
|
+
});
|
|
96
|
+
items.push(...result.items);
|
|
97
|
+
if (result.items.length < pageSize) {
|
|
98
|
+
break;
|
|
99
|
+
}
|
|
100
|
+
if (result.total > 0 && items.length >= result.total) {
|
|
101
|
+
break;
|
|
102
|
+
}
|
|
103
|
+
page += 1;
|
|
104
|
+
}
|
|
105
|
+
return items;
|
|
106
|
+
}
|
|
107
|
+
function assetCollections(asset) {
|
|
108
|
+
const collections = [];
|
|
109
|
+
for (const entry of asset.grouping ?? []) {
|
|
110
|
+
if (Array.isArray(entry)) {
|
|
111
|
+
if (entry[0] === "collection") {
|
|
112
|
+
collections.push(entry[1]);
|
|
113
|
+
}
|
|
114
|
+
continue;
|
|
115
|
+
}
|
|
116
|
+
if (entry.group_key === "collection") {
|
|
117
|
+
collections.push(entry.group_value);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
return collections;
|
|
121
|
+
}
|
|
122
|
+
function normalizeText(value) {
|
|
123
|
+
return String(value).trim().toLowerCase();
|
|
124
|
+
}
|
|
125
|
+
function parseNumericTraitValue(value) {
|
|
126
|
+
if (typeof value === "number") {
|
|
127
|
+
return Number.isFinite(value) ? value : undefined;
|
|
128
|
+
}
|
|
129
|
+
const parsed = Number(value);
|
|
130
|
+
return Number.isFinite(parsed) ? parsed : undefined;
|
|
131
|
+
}
|
|
132
|
+
function matchesStringOp(actual, op) {
|
|
133
|
+
switch (op.op) {
|
|
134
|
+
case "eq":
|
|
135
|
+
return actual === op.value;
|
|
136
|
+
case "neq":
|
|
137
|
+
return actual !== op.value;
|
|
138
|
+
case "in":
|
|
139
|
+
return op.values.includes(actual);
|
|
140
|
+
case "notIn":
|
|
141
|
+
return !op.values.includes(actual);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
function traitEntriesForType(asset, traitType) {
|
|
145
|
+
const normalizedType = traitType.trim().toLowerCase();
|
|
146
|
+
return (asset.content?.metadata?.attributes ?? []).filter((entry) => {
|
|
147
|
+
return (entry.trait_type !== undefined &&
|
|
148
|
+
entry.value !== undefined &&
|
|
149
|
+
entry.trait_type.trim().toLowerCase() === normalizedType);
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
function matchesTraitOp(asset, trait) {
|
|
153
|
+
const entries = traitEntriesForType(asset, trait.trait_type);
|
|
154
|
+
switch (trait.op) {
|
|
155
|
+
case "eq":
|
|
156
|
+
return entries.some((entry) => normalizeText(entry.value) === normalizeText(trait.value));
|
|
157
|
+
case "neq":
|
|
158
|
+
return (entries.length === 0 ||
|
|
159
|
+
entries.every((entry) => normalizeText(entry.value) !== normalizeText(trait.value)));
|
|
160
|
+
case "in": {
|
|
161
|
+
const allowed = new Set(trait.values.map(normalizeText));
|
|
162
|
+
return entries.some((entry) => allowed.has(normalizeText(entry.value)));
|
|
163
|
+
}
|
|
164
|
+
case "notIn": {
|
|
165
|
+
const blocked = new Set(trait.values.map(normalizeText));
|
|
166
|
+
return (entries.length === 0 ||
|
|
167
|
+
entries.every((entry) => !blocked.has(normalizeText(entry.value))));
|
|
168
|
+
}
|
|
169
|
+
case "gte":
|
|
170
|
+
return entries.some((entry) => {
|
|
171
|
+
const numeric = parseNumericTraitValue(entry.value);
|
|
172
|
+
return numeric !== undefined && numeric >= trait.value;
|
|
173
|
+
});
|
|
174
|
+
case "lte":
|
|
175
|
+
return entries.some((entry) => {
|
|
176
|
+
const numeric = parseNumericTraitValue(entry.value);
|
|
177
|
+
return numeric !== undefined && numeric <= trait.value;
|
|
178
|
+
});
|
|
179
|
+
case "between":
|
|
180
|
+
return entries.some((entry) => {
|
|
181
|
+
const numeric = parseNumericTraitValue(entry.value);
|
|
182
|
+
return (numeric !== undefined &&
|
|
183
|
+
numeric >= trait.min &&
|
|
184
|
+
numeric <= trait.max);
|
|
185
|
+
});
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
function matchesTraits(asset, traits) {
|
|
189
|
+
if ("all" in traits) {
|
|
190
|
+
return traits.all.every((trait) => matchesTraitOp(asset, trait));
|
|
191
|
+
}
|
|
192
|
+
return traits.any.some((trait) => matchesTraitOp(asset, trait));
|
|
193
|
+
}
|
|
194
|
+
function assetBalance(asset) {
|
|
195
|
+
const balance = asset.token_info?.balance;
|
|
196
|
+
if (balance === undefined) {
|
|
197
|
+
return 0n;
|
|
198
|
+
}
|
|
199
|
+
return BigInt(balance);
|
|
200
|
+
}
|
|
201
|
+
function matchesBalance(asset, balance) {
|
|
202
|
+
const amount = assetBalance(asset);
|
|
203
|
+
if (balance.min !== undefined && amount < balance.min) {
|
|
204
|
+
return false;
|
|
205
|
+
}
|
|
206
|
+
if (balance.max !== undefined && amount > balance.max) {
|
|
207
|
+
return false;
|
|
208
|
+
}
|
|
209
|
+
return true;
|
|
210
|
+
}
|
|
211
|
+
export function assetMatchesPredicate(asset, predicate) {
|
|
212
|
+
if (predicate.mint !== undefined && !matchesStringOp(asset.id, predicate.mint)) {
|
|
213
|
+
return false;
|
|
214
|
+
}
|
|
215
|
+
if (predicate.collection !== undefined) {
|
|
216
|
+
const collections = assetCollections(asset);
|
|
217
|
+
if (!collections.some((collection) => matchesStringOp(collection, predicate.collection))) {
|
|
218
|
+
return false;
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
if (predicate.traits !== undefined && !matchesTraits(asset, predicate.traits)) {
|
|
222
|
+
return false;
|
|
223
|
+
}
|
|
224
|
+
if (predicate.balance !== undefined && !matchesBalance(asset, predicate.balance)) {
|
|
225
|
+
return false;
|
|
226
|
+
}
|
|
227
|
+
return true;
|
|
228
|
+
}
|
|
229
|
+
function countMatchingAssets(assets, predicate) {
|
|
230
|
+
return assets.filter((asset) => assetMatchesPredicate(asset, predicate)).length;
|
|
231
|
+
}
|
|
232
|
+
function countInRange(count, min, max) {
|
|
233
|
+
if (count < min) {
|
|
234
|
+
return false;
|
|
235
|
+
}
|
|
236
|
+
if (max !== undefined && count > max) {
|
|
237
|
+
return false;
|
|
238
|
+
}
|
|
239
|
+
return true;
|
|
240
|
+
}
|
|
241
|
+
function amountInRange(amount, min, max) {
|
|
242
|
+
if (min !== undefined && amount < min) {
|
|
243
|
+
return false;
|
|
244
|
+
}
|
|
245
|
+
if (max !== undefined && amount > max) {
|
|
246
|
+
return false;
|
|
247
|
+
}
|
|
248
|
+
return true;
|
|
249
|
+
}
|
|
250
|
+
function totalBalanceForMint(assets, mint) {
|
|
251
|
+
let total = 0n;
|
|
252
|
+
for (const asset of assets) {
|
|
253
|
+
if (asset.id === mint) {
|
|
254
|
+
total += assetBalance(asset);
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
return total;
|
|
258
|
+
}
|
|
259
|
+
export function evaluateGatingFilter(assets, filter) {
|
|
260
|
+
if ("count" in filter) {
|
|
261
|
+
const matchCount = countMatchingAssets(assets, filter.count.match);
|
|
262
|
+
return {
|
|
263
|
+
kind: "count",
|
|
264
|
+
filter,
|
|
265
|
+
matchCount,
|
|
266
|
+
passed: countInRange(matchCount, filter.count.min, filter.count.max),
|
|
267
|
+
};
|
|
268
|
+
}
|
|
269
|
+
if ("totalBalance" in filter) {
|
|
270
|
+
const total = totalBalanceForMint(assets, filter.totalBalance.mint);
|
|
271
|
+
return {
|
|
272
|
+
kind: "totalBalance",
|
|
273
|
+
filter,
|
|
274
|
+
total,
|
|
275
|
+
passed: amountInRange(total, filter.totalBalance.min, filter.totalBalance.max),
|
|
276
|
+
};
|
|
277
|
+
}
|
|
278
|
+
if ("and" in filter) {
|
|
279
|
+
const children = filter.and.map((child) => evaluateGatingFilter(assets, child));
|
|
280
|
+
return {
|
|
281
|
+
kind: "and",
|
|
282
|
+
filter,
|
|
283
|
+
passed: children.every((child) => child.passed),
|
|
284
|
+
children,
|
|
285
|
+
};
|
|
286
|
+
}
|
|
287
|
+
if ("or" in filter) {
|
|
288
|
+
const children = filter.or.map((child) => evaluateGatingFilter(assets, child));
|
|
289
|
+
return {
|
|
290
|
+
kind: "or",
|
|
291
|
+
filter,
|
|
292
|
+
passed: children.some((child) => child.passed),
|
|
293
|
+
children,
|
|
294
|
+
};
|
|
295
|
+
}
|
|
296
|
+
if ("not" in filter) {
|
|
297
|
+
const child = evaluateGatingFilter(assets, filter.not);
|
|
298
|
+
return {
|
|
299
|
+
kind: "not",
|
|
300
|
+
filter,
|
|
301
|
+
passed: !child.passed,
|
|
302
|
+
child,
|
|
303
|
+
};
|
|
304
|
+
}
|
|
305
|
+
throw new Error("Invalid gating filter.");
|
|
306
|
+
}
|
|
307
|
+
function formatGatingStringOp(field, op) {
|
|
308
|
+
switch (op.op) {
|
|
309
|
+
case "eq":
|
|
310
|
+
return `${field} = ${op.value}`;
|
|
311
|
+
case "neq":
|
|
312
|
+
return `${field} != ${op.value}`;
|
|
313
|
+
case "in":
|
|
314
|
+
return `${field} in (${op.values.join(", ")})`;
|
|
315
|
+
case "notIn":
|
|
316
|
+
return `${field} not in (${op.values.join(", ")})`;
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
function formatGatingTraitOp(op) {
|
|
320
|
+
switch (op.op) {
|
|
321
|
+
case "eq":
|
|
322
|
+
return `= ${op.value}`;
|
|
323
|
+
case "neq":
|
|
324
|
+
return `!= ${op.value}`;
|
|
325
|
+
case "in":
|
|
326
|
+
return `in (${op.values.join(", ")})`;
|
|
327
|
+
case "notIn":
|
|
328
|
+
return `not in (${op.values.join(", ")})`;
|
|
329
|
+
case "gte":
|
|
330
|
+
return `>= ${op.value}`;
|
|
331
|
+
case "lte":
|
|
332
|
+
return `<= ${op.value}`;
|
|
333
|
+
case "between":
|
|
334
|
+
return `between ${op.min} and ${op.max}`;
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
function formatGatingTrait(trait) {
|
|
338
|
+
return `${trait.trait_type} ${formatGatingTraitOp(trait)}`;
|
|
339
|
+
}
|
|
340
|
+
export function formatGatingPredicate(predicate) {
|
|
341
|
+
const parts = [];
|
|
342
|
+
if (predicate.collection !== undefined) {
|
|
343
|
+
parts.push(formatGatingStringOp("collection", predicate.collection));
|
|
344
|
+
}
|
|
345
|
+
if (predicate.mint !== undefined) {
|
|
346
|
+
parts.push(formatGatingStringOp("mint", predicate.mint));
|
|
347
|
+
}
|
|
348
|
+
if (predicate.traits !== undefined) {
|
|
349
|
+
if ("all" in predicate.traits) {
|
|
350
|
+
parts.push(`traits all [${predicate.traits.all.map(formatGatingTrait).join("; ")}]`);
|
|
351
|
+
}
|
|
352
|
+
else {
|
|
353
|
+
parts.push(`traits any [${predicate.traits.any.map(formatGatingTrait).join("; ")}]`);
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
if (predicate.balance !== undefined) {
|
|
357
|
+
const { min, max } = predicate.balance;
|
|
358
|
+
if (min !== undefined && max !== undefined) {
|
|
359
|
+
parts.push(`balance between ${min} and ${max}`);
|
|
360
|
+
}
|
|
361
|
+
else if (min !== undefined) {
|
|
362
|
+
parts.push(`balance >= ${min}`);
|
|
363
|
+
}
|
|
364
|
+
else if (max !== undefined) {
|
|
365
|
+
parts.push(`balance <= ${max}`);
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
return parts.length > 0 ? parts.join(", ") : "any asset";
|
|
369
|
+
}
|
|
370
|
+
function describeSatisfiedCondition(result) {
|
|
371
|
+
switch (result.kind) {
|
|
372
|
+
case "count":
|
|
373
|
+
return `${result.matchCount} asset(s) matching ${formatGatingPredicate(result.filter.count.match)}`;
|
|
374
|
+
case "totalBalance":
|
|
375
|
+
return `balance ${result.total} for mint ${result.filter.totalBalance.mint}`;
|
|
376
|
+
case "and":
|
|
377
|
+
return result.children.map(describeSatisfiedCondition).join("; ");
|
|
378
|
+
case "or": {
|
|
379
|
+
const passedChild = result.children.find((child) => child.passed);
|
|
380
|
+
return passedChild
|
|
381
|
+
? describeSatisfiedCondition(passedChild)
|
|
382
|
+
: "an alternative condition";
|
|
383
|
+
}
|
|
384
|
+
case "not":
|
|
385
|
+
return `not (${describeSatisfiedCondition(result.child)})`;
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
function summarizeFailedNode(result) {
|
|
389
|
+
switch (result.kind) {
|
|
390
|
+
case "count": {
|
|
391
|
+
const { min, max, match } = result.filter.count;
|
|
392
|
+
const predicate = formatGatingPredicate(match);
|
|
393
|
+
const lines = [];
|
|
394
|
+
if (result.matchCount < min) {
|
|
395
|
+
lines.push(`Need at least ${min} asset(s) matching ${predicate}; found ${result.matchCount}.`);
|
|
396
|
+
}
|
|
397
|
+
if (max !== undefined && result.matchCount > max) {
|
|
398
|
+
lines.push(`Need at most ${max} asset(s) matching ${predicate}; found ${result.matchCount}.`);
|
|
399
|
+
}
|
|
400
|
+
if (lines.length === 0) {
|
|
401
|
+
lines.push(`Asset count requirement not met for ${predicate} (found ${result.matchCount}).`);
|
|
402
|
+
}
|
|
403
|
+
return lines;
|
|
404
|
+
}
|
|
405
|
+
case "totalBalance": {
|
|
406
|
+
const { mint, min, max } = result.filter.totalBalance;
|
|
407
|
+
const lines = [];
|
|
408
|
+
if (min !== undefined && result.total < min) {
|
|
409
|
+
lines.push(`Need at least ${min} raw balance for mint ${mint}; found ${result.total}.`);
|
|
410
|
+
}
|
|
411
|
+
if (max !== undefined && result.total > max) {
|
|
412
|
+
lines.push(`Need at most ${max} raw balance for mint ${mint}; found ${result.total}.`);
|
|
413
|
+
}
|
|
414
|
+
if (lines.length === 0) {
|
|
415
|
+
lines.push(`Balance requirement not met for mint ${mint} (found ${result.total}).`);
|
|
416
|
+
}
|
|
417
|
+
return lines;
|
|
418
|
+
}
|
|
419
|
+
case "and":
|
|
420
|
+
return result.children.flatMap((child) => summarizeGatingFailure(child));
|
|
421
|
+
case "or":
|
|
422
|
+
return [
|
|
423
|
+
"None of the alternative conditions were met:",
|
|
424
|
+
...result.children.flatMap((child, index) => summarizeGatingFailure(child).map((line) => ` [${index + 1}] ${line}`)),
|
|
425
|
+
];
|
|
426
|
+
case "not":
|
|
427
|
+
return [
|
|
428
|
+
`Must not satisfy: ${describeSatisfiedCondition(result.child)}.`,
|
|
429
|
+
];
|
|
430
|
+
}
|
|
431
|
+
}
|
|
432
|
+
export function summarizeGatingFailure(result) {
|
|
433
|
+
if (result.passed) {
|
|
434
|
+
return [];
|
|
435
|
+
}
|
|
436
|
+
return summarizeFailedNode(result);
|
|
437
|
+
}
|
|
438
|
+
export function summarizeGatingTierFailure(tier) {
|
|
439
|
+
return summarizeGatingFailure(tier.filterResult);
|
|
440
|
+
}
|
|
441
|
+
export function summarizeGatingEvaluationFailure(result) {
|
|
442
|
+
if (result.passed) {
|
|
443
|
+
return [];
|
|
444
|
+
}
|
|
445
|
+
return result.tiers.flatMap((tier) => {
|
|
446
|
+
const reasons = summarizeGatingTierFailure(tier);
|
|
447
|
+
if (reasons.length === 0) {
|
|
448
|
+
return [];
|
|
449
|
+
}
|
|
450
|
+
return [`Tier "${tier.id}":`, ...reasons.map((line) => ` ${line}`)];
|
|
451
|
+
});
|
|
452
|
+
}
|
|
453
|
+
export function evaluateGatingTiers(assets, tiers) {
|
|
454
|
+
const tierResults = tiers.map((tier) => {
|
|
455
|
+
const filterResult = evaluateGatingFilter(assets, tier.filter);
|
|
456
|
+
return {
|
|
457
|
+
id: tier.id,
|
|
458
|
+
passed: filterResult.passed,
|
|
459
|
+
filterResult,
|
|
460
|
+
};
|
|
461
|
+
});
|
|
462
|
+
const passedTierIds = tierResults
|
|
463
|
+
.filter((tier) => tier.passed)
|
|
464
|
+
.map((tier) => tier.id);
|
|
465
|
+
return {
|
|
466
|
+
tiers: tierResults,
|
|
467
|
+
passedTierIds,
|
|
468
|
+
passed: passedTierIds.length > 0,
|
|
469
|
+
};
|
|
470
|
+
}
|
|
471
|
+
export async function evaluateAssetGating(options) {
|
|
472
|
+
const { assetPublicKey, rpc, tiers } = options;
|
|
473
|
+
const owner = await fetchAssetOwner(rpc, assetPublicKey);
|
|
474
|
+
const assets = await fetchOwnerDasAssets(owner, rpc);
|
|
475
|
+
const tierEvaluation = evaluateGatingTiers(assets, tiers);
|
|
476
|
+
return {
|
|
477
|
+
...tierEvaluation,
|
|
478
|
+
owner,
|
|
479
|
+
};
|
|
480
|
+
}
|
|
481
|
+
//# sourceMappingURL=gating.js.map
|