@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/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,