@parity/product-sdk 0.26.0 → 0.28.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/package.json +10 -10
- package/src/individuality/contract.test.ts +187 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@parity/product-sdk",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.28.0",
|
|
4
4
|
"description": "Unified SDK for building products in the Polkadot ecosystem - umbrella package",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"sideEffects": false,
|
|
@@ -72,19 +72,19 @@
|
|
|
72
72
|
"dependencies": {
|
|
73
73
|
"polkadot-api": "^2.1.6",
|
|
74
74
|
"@parity/product-sdk-address": "0.2.0",
|
|
75
|
-
"@parity/product-sdk-cloud-storage": "0.
|
|
75
|
+
"@parity/product-sdk-cloud-storage": "0.12.0",
|
|
76
|
+
"@parity/product-sdk-chain-client": "0.12.4",
|
|
76
77
|
"@parity/product-sdk-crypto": "0.1.1",
|
|
77
|
-
"@parity/product-sdk-
|
|
78
|
-
"@parity/product-sdk-contracts": "0.10.
|
|
79
|
-
"@parity/product-sdk-
|
|
80
|
-
"@parity/product-sdk-
|
|
81
|
-
"@parity/product-sdk-keys": "0.3.23",
|
|
78
|
+
"@parity/product-sdk-host": "0.20.0",
|
|
79
|
+
"@parity/product-sdk-contracts": "0.10.8",
|
|
80
|
+
"@parity/product-sdk-individuality": "0.5.0",
|
|
81
|
+
"@parity/product-sdk-keys": "0.3.25",
|
|
82
82
|
"@parity/product-sdk-logger": "0.1.1",
|
|
83
83
|
"@parity/product-sdk-errors": "0.2.0",
|
|
84
|
-
"@parity/product-sdk-
|
|
85
|
-
"@parity/product-sdk-tx": "0.4.6",
|
|
84
|
+
"@parity/product-sdk-signer": "0.14.5",
|
|
86
85
|
"@parity/result": "0.2.0",
|
|
87
|
-
"@parity/product-sdk-
|
|
86
|
+
"@parity/product-sdk-local-storage": "0.3.10",
|
|
87
|
+
"@parity/product-sdk-tx": "0.4.8"
|
|
88
88
|
},
|
|
89
89
|
"peerDependencies": {
|
|
90
90
|
"react": "^18.0.0 || ^19.0.0"
|
|
@@ -32,6 +32,7 @@
|
|
|
32
32
|
*/
|
|
33
33
|
import type { getChainAPI } from "@parity/product-sdk-chain-client";
|
|
34
34
|
import type {
|
|
35
|
+
RingLocation as HostRingLocation,
|
|
35
36
|
RingVRFProof as HostRingVRFProof,
|
|
36
37
|
VrfSignature as HostVrfSignature,
|
|
37
38
|
VrfTranscriptItem as HostVrfTranscriptItem,
|
|
@@ -43,8 +44,16 @@ import type {
|
|
|
43
44
|
GameChain,
|
|
44
45
|
GamePlayersChain,
|
|
45
46
|
IndividualityChain,
|
|
47
|
+
LegacySuffixChain,
|
|
48
|
+
LiteAliasBindChain,
|
|
49
|
+
LiteSignUpChain,
|
|
50
|
+
NetworkSuffixChain,
|
|
46
51
|
PapiIndividualityChain,
|
|
47
52
|
PrizeStatusChain,
|
|
53
|
+
RegisterChain,
|
|
54
|
+
RegistrationEligibilityChain,
|
|
55
|
+
RingLocation as SdkRingLocation,
|
|
56
|
+
ScoreContextChain,
|
|
48
57
|
SignUpChain,
|
|
49
58
|
AccountVrfSignature,
|
|
50
59
|
VrfTranscriptItem as IndividualityVrfTranscriptItem,
|
|
@@ -117,11 +126,50 @@ type FromPapiSatisfiesContracts = Assert<
|
|
|
117
126
|
PapiIndividualityChain<PaseoClient["individuality"]> extends IndividualityChain &
|
|
118
127
|
AirdropChain &
|
|
119
128
|
GameChain &
|
|
120
|
-
GamePlayersChain
|
|
129
|
+
GamePlayersChain &
|
|
130
|
+
ScoreContextChain &
|
|
131
|
+
SignUpChain &
|
|
132
|
+
LiteSignUpChain
|
|
121
133
|
? true
|
|
122
134
|
: false
|
|
123
135
|
>;
|
|
124
136
|
|
|
137
|
+
// Storage is the only way either chain resolves a suffix since the re-pin, so the
|
|
138
|
+
// bring-your-own-client path needs it asserted too.
|
|
139
|
+
type FromPapiSatisfiesTheSuffixStorage = Assert<
|
|
140
|
+
PapiIndividualityChain<
|
|
141
|
+
PaseoClient["individuality"],
|
|
142
|
+
PaseoClient["raw"]["individuality"]
|
|
143
|
+
> extends NetworkSuffixChain
|
|
144
|
+
? true
|
|
145
|
+
: false
|
|
146
|
+
>;
|
|
147
|
+
|
|
148
|
+
type PaseoSatisfiesScoreContext = Assert<PaseoClient extends ScoreContextChain ? true : false>;
|
|
149
|
+
type DevnetSatisfiesScoreContext = Assert<DevnetClient extends ScoreContextChain ? true : false>;
|
|
150
|
+
type PreviewnetSatisfiesScoreContext = Assert<
|
|
151
|
+
PreviewnetClient extends ScoreContextChain ? true : false
|
|
152
|
+
>;
|
|
153
|
+
|
|
154
|
+
// The suffix moved from a constant to storage upstream, and the 2026-09-03 re-pin
|
|
155
|
+
// brought that to both live chains. Devnet still predates it, so it holds the old
|
|
156
|
+
// shape and is the one asserted negatively now.
|
|
157
|
+
type PreviewnetPredatesTheLegacySuffix = Assert<
|
|
158
|
+
PreviewnetClient extends LegacySuffixChain ? false : true
|
|
159
|
+
>;
|
|
160
|
+
type PaseoPredatesTheLegacySuffix = Assert<PaseoClient extends LegacySuffixChain ? false : true>;
|
|
161
|
+
type DevnetPredatesTheLegacySuffix = Assert<DevnetClient extends LegacySuffixChain ? false : true>;
|
|
162
|
+
type PreviewnetHasSuffixStorage = Assert<
|
|
163
|
+
PreviewnetClient extends NetworkSuffixChain ? true : false
|
|
164
|
+
>;
|
|
165
|
+
type PaseoHasSuffixStorage = Assert<PaseoClient extends NetworkSuffixChain ? true : false>;
|
|
166
|
+
type DevnetHasNoSuffixStorage = Assert<DevnetClient extends NetworkSuffixChain ? false : true>;
|
|
167
|
+
|
|
168
|
+
// The two are declared separately, so a rename on either side would go
|
|
169
|
+
// unnoticed anywhere but here.
|
|
170
|
+
type LocalRingLocationFitsHost = Assert<SdkRingLocation extends HostRingLocation ? true : false>;
|
|
171
|
+
type HostRingLocationFitsLocal = Assert<HostRingLocation extends SdkRingLocation ? true : false>;
|
|
172
|
+
|
|
125
173
|
// Negative control, kept type-only so it emits no runtime code. If
|
|
126
174
|
// `IndividualityChain` ever stopped constraining, this flips to `false` and the
|
|
127
175
|
// file fails to typecheck, which is what keeps the assertions above honest.
|
|
@@ -353,6 +401,106 @@ type RejectsItemMissingValue = Assert<
|
|
|
353
401
|
{ label: Uint8Array } extends IndividualityVrfTranscriptItem ? false : true
|
|
354
402
|
>;
|
|
355
403
|
|
|
404
|
+
// The lite sign-up surface: the alias binding, the lite-person marker, the
|
|
405
|
+
// invite pin, the ring membership entry and the free sign-up call. Paseo and
|
|
406
|
+
// previewnet carry all five; devnet predates `Game.LiteInvites` and the call,
|
|
407
|
+
// so it is asserted negatively, like the game surface it composes with.
|
|
408
|
+
type PaseoSatisfiesLiteSignUpContract = Assert<PaseoClient extends LiteSignUpChain ? true : false>;
|
|
409
|
+
type PreviewnetSatisfiesLiteSignUpContract = Assert<
|
|
410
|
+
PreviewnetClient extends LiteSignUpChain ? true : false
|
|
411
|
+
>;
|
|
412
|
+
type DevnetPredatesTheLiteSignUpContract = Assert<
|
|
413
|
+
DevnetClient extends LiteSignUpChain ? false : true
|
|
414
|
+
>;
|
|
415
|
+
type RejectsBogusLiteSignUpClient = Assert<
|
|
416
|
+
ClientWithoutIndividuality extends LiteSignUpChain ? false : true
|
|
417
|
+
>;
|
|
418
|
+
|
|
419
|
+
// `LiteSignUpChain` alone proves nothing about what the read accepts: it takes
|
|
420
|
+
// an intersection and resolves a suffix.
|
|
421
|
+
type LiteSignUpReadBase = GameChain & SignUpChain & ScoreContextChain & LiteSignUpChain;
|
|
422
|
+
type PaseoSatisfiesTheLiteReadWithATld = Assert<
|
|
423
|
+
PaseoClient extends LiteSignUpReadBase ? true : false
|
|
424
|
+
>;
|
|
425
|
+
// Both chains resolve the suffix from storage since the 2026-09-03 re-pin, so the
|
|
426
|
+
// storage overload is the live path and neither can use the constant one.
|
|
427
|
+
type PaseoSatisfiesTheLiteReadFromStorage = Assert<
|
|
428
|
+
PaseoClient extends LiteSignUpReadBase & NetworkSuffixChain ? true : false
|
|
429
|
+
>;
|
|
430
|
+
type PreviewnetSatisfiesTheLiteReadFromStorage = Assert<
|
|
431
|
+
PreviewnetClient extends LiteSignUpReadBase & NetworkSuffixChain ? true : false
|
|
432
|
+
>;
|
|
433
|
+
type NeitherChainHasTheLegacyConstant = Assert<
|
|
434
|
+
PaseoClient | PreviewnetClient extends LiteSignUpReadBase & LegacySuffixChain ? false : true
|
|
435
|
+
>;
|
|
436
|
+
type DevnetPredatesTheLiteRead = Assert<DevnetClient extends LiteSignUpReadBase ? false : true>;
|
|
437
|
+
|
|
438
|
+
// Wider than the reads above: the builder assembles the extrinsic itself, so it
|
|
439
|
+
// needs the chain spec and the metadata blob, not just the call.
|
|
440
|
+
type PaseoSatisfiesBindContract = Assert<PaseoClient extends LiteAliasBindChain ? true : false>;
|
|
441
|
+
type PreviewnetSatisfiesBindContract = Assert<
|
|
442
|
+
PreviewnetClient extends LiteAliasBindChain ? true : false
|
|
443
|
+
>;
|
|
444
|
+
type DevnetSatisfiesBindContract = Assert<DevnetClient extends LiteAliasBindChain ? true : false>;
|
|
445
|
+
type FromPapiSatisfiesBindContract = Assert<
|
|
446
|
+
PapiIndividualityChain<
|
|
447
|
+
PaseoClient["individuality"],
|
|
448
|
+
PaseoClient["raw"]["individuality"]
|
|
449
|
+
> extends LiteAliasBindChain
|
|
450
|
+
? true
|
|
451
|
+
: false
|
|
452
|
+
>;
|
|
453
|
+
type RejectsBogusBindClient = Assert<
|
|
454
|
+
ClientWithoutIndividuality extends LiteAliasBindChain ? false : true
|
|
455
|
+
>;
|
|
456
|
+
|
|
457
|
+
// Pinned by name for the same reason `sign_up_with_account`'s are: PAPI encodes
|
|
458
|
+
// the object it is handed, so a renamed field silently encodes as `undefined` —
|
|
459
|
+
// and `account` here is a call argument, not implied by the signer.
|
|
460
|
+
type LiteInviteArgs = Parameters<GameTx["sign_up_with_account_lite_invite"]>[0];
|
|
461
|
+
type LiteInviteTakesTheDocumentedArgs = Assert<
|
|
462
|
+
"account" extends keyof LiteInviteArgs
|
|
463
|
+
? "identifier_key" extends keyof LiteInviteArgs
|
|
464
|
+
? "airdrops" extends keyof LiteInviteArgs
|
|
465
|
+
? true
|
|
466
|
+
: false
|
|
467
|
+
: false
|
|
468
|
+
: false
|
|
469
|
+
>;
|
|
470
|
+
type LiteInviteAirdropsIsOptional = Assert<
|
|
471
|
+
undefined extends LiteInviteArgs["airdrops"] ? true : false
|
|
472
|
+
>;
|
|
473
|
+
|
|
474
|
+
// `PeopleLite.AccountToAlias`: the three fields the lite requirement read uses.
|
|
475
|
+
// The context matters as much as the alias — a binding outside the score
|
|
476
|
+
// context does not satisfy the game's origin check — so it is pinned by name.
|
|
477
|
+
type LiteBindingValue = NonNullable<
|
|
478
|
+
Awaited<
|
|
479
|
+
ReturnType<
|
|
480
|
+
PaseoClient["individuality"]["query"]["PeopleLite"]["AccountToAlias"]["getValue"]
|
|
481
|
+
>
|
|
482
|
+
>
|
|
483
|
+
>;
|
|
484
|
+
type LiteBindingHasTheDocumentedFields = Assert<
|
|
485
|
+
"revision" extends keyof LiteBindingValue
|
|
486
|
+
? "ring" extends keyof LiteBindingValue
|
|
487
|
+
? LiteBindingValue["ca"] extends { alias: string; context: string }
|
|
488
|
+
? true
|
|
489
|
+
: false
|
|
490
|
+
: false
|
|
491
|
+
: false
|
|
492
|
+
>;
|
|
493
|
+
|
|
494
|
+
// `Members.Members` is a double map (collection id, member key), which is what
|
|
495
|
+
// lets the membership check be a point read. A collapsed key would silently
|
|
496
|
+
// turn the varargs call into a mistyped one, so the arity is pinned.
|
|
497
|
+
type MembersKey = Parameters<
|
|
498
|
+
PaseoClient["individuality"]["query"]["Members"]["Members"]["getValue"]
|
|
499
|
+
>;
|
|
500
|
+
type MembersTakesTwoKeys = Assert<
|
|
501
|
+
MembersKey extends [unknown, unknown, ...unknown[]] ? true : false
|
|
502
|
+
>;
|
|
503
|
+
|
|
356
504
|
// `Game.Players`: the variant spelling the read keys by, and the one field it uses.
|
|
357
505
|
// Sibling reads got exactly these pins.
|
|
358
506
|
type PlayersEntry = PaseoClient["individuality"]["query"]["Game"]["Players"];
|
|
@@ -366,6 +514,44 @@ type RejectsAliasSpelling = Assert<
|
|
|
366
514
|
type PlayersValue = NonNullable<Awaited<ReturnType<PlayersEntry["getValue"]>>>;
|
|
367
515
|
type PlayersHasRegistered = Assert<"registered" extends keyof PlayersValue ? true : false>;
|
|
368
516
|
|
|
517
|
+
type PaseoSatisfiesRegisterContract = Assert<PaseoClient extends RegisterChain ? true : false>;
|
|
518
|
+
type PreviewnetSatisfiesRegisterContract = Assert<
|
|
519
|
+
PreviewnetClient extends RegisterChain ? true : false
|
|
520
|
+
>;
|
|
521
|
+
type DevnetSatisfiesRegisterContract = Assert<DevnetClient extends RegisterChain ? true : false>;
|
|
522
|
+
type RejectsBogusRegisterClient = Assert<
|
|
523
|
+
ClientWithoutIndividuality extends RegisterChain ? false : true
|
|
524
|
+
>;
|
|
525
|
+
|
|
526
|
+
type PaseoSatisfiesEligibilityContract = Assert<
|
|
527
|
+
PaseoClient extends RegistrationEligibilityChain ? true : false
|
|
528
|
+
>;
|
|
529
|
+
type PreviewnetSatisfiesEligibilityContract = Assert<
|
|
530
|
+
PreviewnetClient extends RegistrationEligibilityChain ? true : false
|
|
531
|
+
>;
|
|
532
|
+
type DevnetSatisfiesEligibilityContract = Assert<
|
|
533
|
+
DevnetClient extends RegistrationEligibilityChain ? true : false
|
|
534
|
+
>;
|
|
535
|
+
type RejectsBogusEligibilityClient = Assert<
|
|
536
|
+
ClientWithoutIndividuality extends RegistrationEligibilityChain ? false : true
|
|
537
|
+
>;
|
|
538
|
+
|
|
539
|
+
// The same trap as `claim_airdrop`'s pins, and worse: `key` is an `Option`, so a
|
|
540
|
+
// renamed argument encodes as `None` — the resume arm this builder never means.
|
|
541
|
+
type ScoreTx = PaseoClient["individuality"]["tx"]["Score"];
|
|
542
|
+
type RegisterExists = Assert<"register" extends keyof ScoreTx ? true : false>;
|
|
543
|
+
type RegisterArgs = Parameters<ScoreTx["register"]>[0];
|
|
544
|
+
type RegisterTakesKey = Assert<"key" extends keyof RegisterArgs ? true : false>;
|
|
545
|
+
type RegisterKeyIsOptional = Assert<undefined extends RegisterArgs["key"] ? true : false>;
|
|
546
|
+
|
|
547
|
+
// `ValueQuery` is what lets the read type the threshold as a plain number, and
|
|
548
|
+
// `Participants` being optional is what makes "never seen" a null, not a throw.
|
|
549
|
+
type ScoreStorage = PaseoClient["individuality"]["query"]["Score"];
|
|
550
|
+
type ThresholdValue = Awaited<ReturnType<ScoreStorage["PersonhoodThreshold"]["getValue"]>>;
|
|
551
|
+
type ThresholdIsNotOptional = Assert<undefined extends ThresholdValue ? false : true>;
|
|
552
|
+
type ParticipantsValue = Awaited<ReturnType<ScoreStorage["Participants"]["getValue"]>>;
|
|
553
|
+
type ParticipantsIsOptional = Assert<undefined extends ParticipantsValue ? true : false>;
|
|
554
|
+
|
|
369
555
|
test("the individuality chain contract is asserted at compile time", () => {
|
|
370
556
|
// The type assertions above are the test. This keeps vitest from reporting
|
|
371
557
|
// the file as an empty suite.
|