@plasius/economy 0.5.0 → 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 +15 -0
- package/dist/index.cjs +268 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +74 -4
- package/dist/index.d.ts +74 -4
- package/dist/index.js +261 -2
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -745,7 +745,8 @@ var COMMAND_TYPES = /* @__PURE__ */ new Set([
|
|
|
745
745
|
"refund",
|
|
746
746
|
"chargeback",
|
|
747
747
|
"reverse",
|
|
748
|
-
"adjust"
|
|
748
|
+
"adjust",
|
|
749
|
+
"initialize-wallet"
|
|
749
750
|
]);
|
|
750
751
|
var COMMAND_SOURCES = /* @__PURE__ */ new Set([
|
|
751
752
|
"browser",
|
|
@@ -792,7 +793,8 @@ var SOURCE_COMMAND_TYPES = {
|
|
|
792
793
|
"reclaim",
|
|
793
794
|
"spend",
|
|
794
795
|
"hold",
|
|
795
|
-
"release-hold"
|
|
796
|
+
"release-hold",
|
|
797
|
+
"initialize-wallet"
|
|
796
798
|
]),
|
|
797
799
|
shopify: /* @__PURE__ */ new Set([
|
|
798
800
|
"credit-purchase",
|
|
@@ -987,6 +989,13 @@ function assertCommandSourcePrincipal(envelope) {
|
|
|
987
989
|
"Delegated-child commands require a distinct actor and relationship"
|
|
988
990
|
);
|
|
989
991
|
}
|
|
992
|
+
if (envelope.commandType === "initialize-wallet") {
|
|
993
|
+
economyAssert(
|
|
994
|
+
envelope.commandSource === "browser" && envelope.principalType === "account" && envelope.actorAccountId === envelope.subjectAccountId && envelope.relationshipId === void 0 && envelope.authorizationVersion === void 0,
|
|
995
|
+
"INVALID_CONTRACT",
|
|
996
|
+
"Wallet initialization requires a direct self-account browser command"
|
|
997
|
+
);
|
|
998
|
+
}
|
|
990
999
|
}
|
|
991
1000
|
function assertAuditedEconomyCommandEnvelope(envelope) {
|
|
992
1001
|
assertExactKeys(
|
|
@@ -1588,6 +1597,7 @@ var RECORD_KINDS = /* @__PURE__ */ new Set([
|
|
|
1588
1597
|
"source-lot",
|
|
1589
1598
|
"source-lot-movement",
|
|
1590
1599
|
"gameplay-allocation",
|
|
1600
|
+
"wallet",
|
|
1591
1601
|
"balance-projection",
|
|
1592
1602
|
"lifetime-projection",
|
|
1593
1603
|
"idempotency-result",
|
|
@@ -2775,6 +2785,13 @@ function assertReceiptGraph(graph, commandEnvelopeHash, hash, acceptanceCommit,
|
|
|
2775
2785
|
result.receiptId,
|
|
2776
2786
|
resultHash
|
|
2777
2787
|
);
|
|
2788
|
+
if (envelope.commandType === "initialize-wallet") {
|
|
2789
|
+
economyAssert(
|
|
2790
|
+
result.outcome === "no-op" && (result.noOpCode === "WALLET_INITIALIZED" || result.noOpCode === "WALLET_ALREADY_INITIALIZED"),
|
|
2791
|
+
"INVALID_CONTRACT",
|
|
2792
|
+
"Wallet initialization must terminate without an economic transaction"
|
|
2793
|
+
);
|
|
2794
|
+
}
|
|
2778
2795
|
if (result.outcome !== "completed") {
|
|
2779
2796
|
economyAssert(
|
|
2780
2797
|
graph.transaction === void 0,
|
|
@@ -8111,6 +8128,241 @@ function assertSpendRequest(request) {
|
|
|
8111
8128
|
);
|
|
8112
8129
|
}
|
|
8113
8130
|
}
|
|
8131
|
+
|
|
8132
|
+
// src/wallet-initialization.ts
|
|
8133
|
+
var INITIALIZATION_IDENTITY_DOMAIN = "economy.personal-wallet-initialization.identity.v1";
|
|
8134
|
+
var ZERO_TOKEN_SUBUNITS = serializeTokenSubunits(0n);
|
|
8135
|
+
var STATE_KEYS = /* @__PURE__ */ new Set([
|
|
8136
|
+
"schemaVersion",
|
|
8137
|
+
"documentIds",
|
|
8138
|
+
"command",
|
|
8139
|
+
"wallet",
|
|
8140
|
+
"scope",
|
|
8141
|
+
"balance",
|
|
8142
|
+
"lifetime",
|
|
8143
|
+
"activityEntries",
|
|
8144
|
+
"outboxIntent"
|
|
8145
|
+
]);
|
|
8146
|
+
var COMMAND_KEYS = /* @__PURE__ */ new Set([
|
|
8147
|
+
"schemaVersion",
|
|
8148
|
+
"commandType",
|
|
8149
|
+
"walletKind",
|
|
8150
|
+
"subjectAccountId",
|
|
8151
|
+
"walletId",
|
|
8152
|
+
"portfolioId",
|
|
8153
|
+
"initializedAt"
|
|
8154
|
+
]);
|
|
8155
|
+
var OUTBOX_KEYS = /* @__PURE__ */ new Set([
|
|
8156
|
+
"schemaVersion",
|
|
8157
|
+
"eventType",
|
|
8158
|
+
"eventId",
|
|
8159
|
+
"subjectAccountId",
|
|
8160
|
+
"walletId",
|
|
8161
|
+
"portfolioId",
|
|
8162
|
+
"occurredAt"
|
|
8163
|
+
]);
|
|
8164
|
+
var DOCUMENT_ID_KEYS = /* @__PURE__ */ new Set([
|
|
8165
|
+
"walletDescriptorId",
|
|
8166
|
+
"accessProjectionId",
|
|
8167
|
+
"balanceProjectionId",
|
|
8168
|
+
"lifetimeProjectionId",
|
|
8169
|
+
"outboxEventId"
|
|
8170
|
+
]);
|
|
8171
|
+
function assertExactKeys4(value, allowed, label) {
|
|
8172
|
+
economyAssert(
|
|
8173
|
+
value !== null && typeof value === "object" && !Array.isArray(value),
|
|
8174
|
+
"INVALID_CONTRACT",
|
|
8175
|
+
`${label} must be an object`
|
|
8176
|
+
);
|
|
8177
|
+
economyAssert(
|
|
8178
|
+
Object.keys(value).every((key) => allowed.has(key)),
|
|
8179
|
+
"INVALID_CONTRACT",
|
|
8180
|
+
`${label} contains an unsupported field`
|
|
8181
|
+
);
|
|
8182
|
+
}
|
|
8183
|
+
function identityDigest(subjectAccountId, hash) {
|
|
8184
|
+
assertEconomyIdentifier(subjectAccountId, "subjectAccountId");
|
|
8185
|
+
const canonicalIdentity = JSON.stringify({
|
|
8186
|
+
schemaVersion: ECONOMY_CONTRACT_VERSION,
|
|
8187
|
+
domain: INITIALIZATION_IDENTITY_DOMAIN,
|
|
8188
|
+
subjectAccountId
|
|
8189
|
+
});
|
|
8190
|
+
const canonicalHash2 = hash(canonicalIdentity);
|
|
8191
|
+
economyAssert(
|
|
8192
|
+
/^sha256:[a-f0-9]{64}$/u.test(canonicalHash2),
|
|
8193
|
+
"INVALID_CONTRACT",
|
|
8194
|
+
"Wallet initialization identity hash must be canonical SHA-256"
|
|
8195
|
+
);
|
|
8196
|
+
return canonicalHash2.slice("sha256:".length);
|
|
8197
|
+
}
|
|
8198
|
+
function createPersonalWalletInitializationDocumentIds(subjectAccountId, hash) {
|
|
8199
|
+
const digest = identityDigest(subjectAccountId, hash);
|
|
8200
|
+
return {
|
|
8201
|
+
walletId: `wallet:personal:${digest}`,
|
|
8202
|
+
portfolioId: `portfolio:self:${digest}`,
|
|
8203
|
+
walletDescriptorId: `wallet-descriptor:${digest}`,
|
|
8204
|
+
accessProjectionId: `wallet-access:${digest}`,
|
|
8205
|
+
balanceProjectionId: `wallet-balance:${digest}`,
|
|
8206
|
+
lifetimeProjectionId: `wallet-lifetime:${digest}`,
|
|
8207
|
+
outboxEventId: `outbox:wallet-initialized:${digest}`
|
|
8208
|
+
};
|
|
8209
|
+
}
|
|
8210
|
+
function assertPersonalWalletInitializationCommand(command) {
|
|
8211
|
+
assertExactKeys4(command, COMMAND_KEYS, "Wallet initialization command");
|
|
8212
|
+
economyAssert(
|
|
8213
|
+
command.schemaVersion === ECONOMY_CONTRACT_VERSION && command.commandType === "initialize-wallet" && command.walletKind === "personal",
|
|
8214
|
+
"INVALID_CONTRACT",
|
|
8215
|
+
"Unsupported personal-wallet initialization command"
|
|
8216
|
+
);
|
|
8217
|
+
assertEconomyIdentifier(command.subjectAccountId, "subjectAccountId");
|
|
8218
|
+
assertEconomyIdentifier(command.walletId, "walletId");
|
|
8219
|
+
assertEconomyIdentifier(command.portfolioId, "portfolioId");
|
|
8220
|
+
parseIsoTimestamp(command.initializedAt);
|
|
8221
|
+
}
|
|
8222
|
+
function canonicalPersonalWalletInitializationCommandPayload(command) {
|
|
8223
|
+
assertPersonalWalletInitializationCommand(command);
|
|
8224
|
+
return JSON.stringify({
|
|
8225
|
+
schemaVersion: command.schemaVersion,
|
|
8226
|
+
commandType: command.commandType,
|
|
8227
|
+
walletKind: command.walletKind,
|
|
8228
|
+
subjectAccountId: command.subjectAccountId,
|
|
8229
|
+
walletId: command.walletId,
|
|
8230
|
+
portfolioId: command.portfolioId,
|
|
8231
|
+
initializedAt: command.initializedAt
|
|
8232
|
+
});
|
|
8233
|
+
}
|
|
8234
|
+
function assertPersonalWalletInitializationOutboxIntent(intent) {
|
|
8235
|
+
assertExactKeys4(intent, OUTBOX_KEYS, "Wallet initialization outbox intent");
|
|
8236
|
+
economyAssert(
|
|
8237
|
+
intent.schemaVersion === ECONOMY_CONTRACT_VERSION && intent.eventType === "wallet.initialized.v1",
|
|
8238
|
+
"INVALID_CONTRACT",
|
|
8239
|
+
"Unsupported wallet initialization outbox intent"
|
|
8240
|
+
);
|
|
8241
|
+
assertEconomyIdentifier(intent.eventId, "eventId");
|
|
8242
|
+
assertEconomyIdentifier(intent.subjectAccountId, "subjectAccountId");
|
|
8243
|
+
assertEconomyIdentifier(intent.walletId, "walletId");
|
|
8244
|
+
assertEconomyIdentifier(intent.portfolioId, "portfolioId");
|
|
8245
|
+
parseIsoTimestamp(intent.occurredAt);
|
|
8246
|
+
}
|
|
8247
|
+
function canonicalPersonalWalletInitializationOutboxPayload(intent) {
|
|
8248
|
+
assertPersonalWalletInitializationOutboxIntent(intent);
|
|
8249
|
+
return JSON.stringify({
|
|
8250
|
+
schemaVersion: intent.schemaVersion,
|
|
8251
|
+
eventType: intent.eventType,
|
|
8252
|
+
eventId: intent.eventId,
|
|
8253
|
+
subjectAccountId: intent.subjectAccountId,
|
|
8254
|
+
walletId: intent.walletId,
|
|
8255
|
+
portfolioId: intent.portfolioId,
|
|
8256
|
+
occurredAt: intent.occurredAt
|
|
8257
|
+
});
|
|
8258
|
+
}
|
|
8259
|
+
function createPersonalWalletInitializationState(input, hash) {
|
|
8260
|
+
parseIsoTimestamp(input.initializedAt);
|
|
8261
|
+
const { walletId, portfolioId, ...documentIds } = createPersonalWalletInitializationDocumentIds(
|
|
8262
|
+
input.subjectAccountId,
|
|
8263
|
+
hash
|
|
8264
|
+
);
|
|
8265
|
+
const command = {
|
|
8266
|
+
schemaVersion: ECONOMY_CONTRACT_VERSION,
|
|
8267
|
+
commandType: "initialize-wallet",
|
|
8268
|
+
walletKind: "personal",
|
|
8269
|
+
subjectAccountId: input.subjectAccountId,
|
|
8270
|
+
walletId,
|
|
8271
|
+
portfolioId,
|
|
8272
|
+
initializedAt: input.initializedAt
|
|
8273
|
+
};
|
|
8274
|
+
const state = {
|
|
8275
|
+
schemaVersion: ECONOMY_CONTRACT_VERSION,
|
|
8276
|
+
documentIds,
|
|
8277
|
+
command,
|
|
8278
|
+
wallet: {
|
|
8279
|
+
schemaVersion: ECONOMY_CONTRACT_VERSION,
|
|
8280
|
+
walletId,
|
|
8281
|
+
accountId: input.subjectAccountId,
|
|
8282
|
+
kind: "personal",
|
|
8283
|
+
ownerType: "account",
|
|
8284
|
+
ownerId: input.subjectAccountId,
|
|
8285
|
+
status: "active",
|
|
8286
|
+
version: 1,
|
|
8287
|
+
createdAt: input.initializedAt
|
|
8288
|
+
},
|
|
8289
|
+
scope: {
|
|
8290
|
+
schemaVersion: ECONOMY_CONTRACT_VERSION,
|
|
8291
|
+
portfolioId,
|
|
8292
|
+
subjectAccountId: input.subjectAccountId,
|
|
8293
|
+
components: [{ walletId, role: "personal" }]
|
|
8294
|
+
},
|
|
8295
|
+
balance: {
|
|
8296
|
+
schemaVersion: ECONOMY_CONTRACT_VERSION,
|
|
8297
|
+
walletId,
|
|
8298
|
+
available: ZERO_TOKEN_SUBUNITS,
|
|
8299
|
+
reserved: ZERO_TOKEN_SUBUNITS,
|
|
8300
|
+
held: ZERO_TOKEN_SUBUNITS,
|
|
8301
|
+
rewardProgress: ZERO_TOKEN_SUBUNITS,
|
|
8302
|
+
version: 1,
|
|
8303
|
+
asOf: input.initializedAt
|
|
8304
|
+
},
|
|
8305
|
+
lifetime: {
|
|
8306
|
+
schemaVersion: ECONOMY_CONTRACT_VERSION,
|
|
8307
|
+
walletId,
|
|
8308
|
+
totals: {
|
|
8309
|
+
schemaVersion: ECONOMY_CONTRACT_VERSION,
|
|
8310
|
+
bought: ZERO_TOKEN_SUBUNITS,
|
|
8311
|
+
earned: ZERO_TOKEN_SUBUNITS,
|
|
8312
|
+
allocated: ZERO_TOKEN_SUBUNITS,
|
|
8313
|
+
reclaimed: ZERO_TOKEN_SUBUNITS,
|
|
8314
|
+
spent: ZERO_TOKEN_SUBUNITS,
|
|
8315
|
+
reversed: ZERO_TOKEN_SUBUNITS
|
|
8316
|
+
},
|
|
8317
|
+
version: 1,
|
|
8318
|
+
asOf: input.initializedAt
|
|
8319
|
+
},
|
|
8320
|
+
activityEntries: [],
|
|
8321
|
+
outboxIntent: {
|
|
8322
|
+
schemaVersion: ECONOMY_CONTRACT_VERSION,
|
|
8323
|
+
eventType: "wallet.initialized.v1",
|
|
8324
|
+
eventId: documentIds.outboxEventId,
|
|
8325
|
+
subjectAccountId: input.subjectAccountId,
|
|
8326
|
+
walletId,
|
|
8327
|
+
portfolioId,
|
|
8328
|
+
occurredAt: input.initializedAt
|
|
8329
|
+
}
|
|
8330
|
+
};
|
|
8331
|
+
assertPersonalWalletInitializationState(state);
|
|
8332
|
+
return state;
|
|
8333
|
+
}
|
|
8334
|
+
function assertPersonalWalletInitializationState(state) {
|
|
8335
|
+
assertExactKeys4(state, STATE_KEYS, "Wallet initialization state");
|
|
8336
|
+
assertExactKeys4(
|
|
8337
|
+
state.documentIds,
|
|
8338
|
+
DOCUMENT_ID_KEYS,
|
|
8339
|
+
"Wallet initialization document IDs"
|
|
8340
|
+
);
|
|
8341
|
+
economyAssert(
|
|
8342
|
+
state.schemaVersion === ECONOMY_CONTRACT_VERSION,
|
|
8343
|
+
"INVALID_CONTRACT",
|
|
8344
|
+
"Unsupported wallet initialization state"
|
|
8345
|
+
);
|
|
8346
|
+
for (const identifier of Object.values(state.documentIds)) {
|
|
8347
|
+
assertEconomyIdentifier(identifier, "wallet initialization document ID");
|
|
8348
|
+
}
|
|
8349
|
+
economyAssert(
|
|
8350
|
+
new Set(Object.values(state.documentIds)).size === Object.values(state.documentIds).length,
|
|
8351
|
+
"INVALID_CONTRACT",
|
|
8352
|
+
"Wallet initialization document IDs must be unique"
|
|
8353
|
+
);
|
|
8354
|
+
assertPersonalWalletInitializationCommand(state.command);
|
|
8355
|
+
assertWallet(state.wallet);
|
|
8356
|
+
assertWalletPortfolioReadScope(state.scope);
|
|
8357
|
+
assertWalletBalanceSummary(state.balance);
|
|
8358
|
+
assertWalletLifetimeSnapshot(state.lifetime);
|
|
8359
|
+
assertPersonalWalletInitializationOutboxIntent(state.outboxIntent);
|
|
8360
|
+
economyAssert(
|
|
8361
|
+
state.wallet.walletId === state.command.walletId && state.wallet.accountId === state.command.subjectAccountId && state.wallet.ownerId === state.command.subjectAccountId && state.wallet.kind === "personal" && state.wallet.ownerType === "account" && state.wallet.createdAt === state.command.initializedAt && state.scope.portfolioId === state.command.portfolioId && state.scope.subjectAccountId === state.command.subjectAccountId && state.scope.components.length === 1 && state.scope.components[0]?.walletId === state.command.walletId && state.scope.components[0]?.role === "personal" && state.scope.components[0]?.beneficiaryAccountId === void 0 && state.balance.walletId === state.command.walletId && state.balance.available === ZERO_TOKEN_SUBUNITS && state.balance.reserved === ZERO_TOKEN_SUBUNITS && state.balance.held === ZERO_TOKEN_SUBUNITS && state.balance.rewardProgress === ZERO_TOKEN_SUBUNITS && state.balance.version === 1 && state.balance.asOf === state.command.initializedAt && state.lifetime.walletId === state.command.walletId && state.lifetime.version === 1 && state.lifetime.asOf === state.command.initializedAt && state.lifetime.totals.bought === ZERO_TOKEN_SUBUNITS && state.lifetime.totals.earned === ZERO_TOKEN_SUBUNITS && state.lifetime.totals.allocated === ZERO_TOKEN_SUBUNITS && state.lifetime.totals.reclaimed === ZERO_TOKEN_SUBUNITS && state.lifetime.totals.spent === ZERO_TOKEN_SUBUNITS && state.lifetime.totals.reversed === ZERO_TOKEN_SUBUNITS && state.activityEntries.length === 0 && state.outboxIntent.eventId === state.documentIds.outboxEventId && state.outboxIntent.subjectAccountId === state.command.subjectAccountId && state.outboxIntent.walletId === state.command.walletId && state.outboxIntent.portfolioId === state.command.portfolioId && state.outboxIntent.occurredAt === state.command.initializedAt,
|
|
8362
|
+
"INVALID_CONTRACT",
|
|
8363
|
+
"Personal-wallet initialization state is incomplete or inconsistent"
|
|
8364
|
+
);
|
|
8365
|
+
}
|
|
8114
8366
|
export {
|
|
8115
8367
|
BASELINE_GBP_CATALOG_VERSION,
|
|
8116
8368
|
BASELINE_GBP_REFERENCE_RATE,
|
|
@@ -8195,6 +8447,9 @@ export {
|
|
|
8195
8447
|
assertPaidLotLifecycle,
|
|
8196
8448
|
assertPaidLotLifecycleEvent,
|
|
8197
8449
|
assertPaidLotPurchaseProvenance,
|
|
8450
|
+
assertPersonalWalletInitializationCommand,
|
|
8451
|
+
assertPersonalWalletInitializationOutboxIntent,
|
|
8452
|
+
assertPersonalWalletInitializationState,
|
|
8198
8453
|
assertPurchaseCapReservation,
|
|
8199
8454
|
assertPurchaseCapReservationTransition,
|
|
8200
8455
|
assertPurchaseIntentBinding,
|
|
@@ -8252,6 +8507,8 @@ export {
|
|
|
8252
8507
|
canonicalEconomyRegionalEvidenceReceiptBodyPayload,
|
|
8253
8508
|
canonicalEconomyRegionalEvidenceReceiptPayload,
|
|
8254
8509
|
canonicalEconomyRegionalEvidenceReceiptSigningPayload,
|
|
8510
|
+
canonicalPersonalWalletInitializationCommandPayload,
|
|
8511
|
+
canonicalPersonalWalletInitializationOutboxPayload,
|
|
8255
8512
|
canonicalTransactionPayload,
|
|
8256
8513
|
closeModuleAllowance,
|
|
8257
8514
|
convertRewardPayout,
|
|
@@ -8267,6 +8524,8 @@ export {
|
|
|
8267
8524
|
createModuleSpendHold,
|
|
8268
8525
|
createModuleSpendQuote,
|
|
8269
8526
|
createPaidLotLifecycle,
|
|
8527
|
+
createPersonalWalletInitializationDocumentIds,
|
|
8528
|
+
createPersonalWalletInitializationState,
|
|
8270
8529
|
createProjectionSnapshot,
|
|
8271
8530
|
createPurchaseIntentLifecycle,
|
|
8272
8531
|
createReversalTransaction,
|