@plasius/economy 0.7.0 → 0.8.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 +62 -0
- package/dist/index.cjs +1260 -65
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +324 -1
- package/dist/index.d.ts +324 -1
- package/dist/index.js +1237 -65
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -20,6 +20,13 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
20
20
|
// src/index.ts
|
|
21
21
|
var index_exports = {};
|
|
22
22
|
__export(index_exports, {
|
|
23
|
+
ADMIN_TOKEN_ANOMALY_BASELINE_DAYS: () => ADMIN_TOKEN_ANOMALY_BASELINE_DAYS,
|
|
24
|
+
ADMIN_TOKEN_DEFAULT_WINDOW_DAYS: () => ADMIN_TOKEN_DEFAULT_WINDOW_DAYS,
|
|
25
|
+
ADMIN_TOKEN_MAXIMUM_HOURLY_WINDOW_DAYS: () => ADMIN_TOKEN_MAXIMUM_HOURLY_WINDOW_DAYS,
|
|
26
|
+
ADMIN_TOKEN_MAXIMUM_PAGE_SIZE: () => ADMIN_TOKEN_MAXIMUM_PAGE_SIZE,
|
|
27
|
+
ADMIN_TOKEN_MAXIMUM_TREND_POINTS: () => ADMIN_TOKEN_MAXIMUM_TREND_POINTS,
|
|
28
|
+
ADMIN_TOKEN_MAXIMUM_WINDOW_DAYS: () => ADMIN_TOKEN_MAXIMUM_WINDOW_DAYS,
|
|
29
|
+
ADMIN_TOKEN_MINIMUM_COHORT_SIZE: () => ADMIN_TOKEN_MINIMUM_COHORT_SIZE,
|
|
23
30
|
BASELINE_GBP_CATALOG_VERSION: () => BASELINE_GBP_CATALOG_VERSION,
|
|
24
31
|
BASELINE_GBP_REFERENCE_RATE: () => BASELINE_GBP_REFERENCE_RATE,
|
|
25
32
|
BASELINE_GBP_TOKEN_PACKS: () => BASELINE_GBP_TOKEN_PACKS,
|
|
@@ -47,6 +54,19 @@ __export(index_exports, {
|
|
|
47
54
|
applyWalletBalanceDelta: () => applyWalletBalanceDelta,
|
|
48
55
|
applyWalletLifetimeDeltas: () => applyWalletLifetimeDeltas,
|
|
49
56
|
assertActivityEntry: () => assertActivityEntry,
|
|
57
|
+
assertAdminTokenActivityCursorBinding: () => assertAdminTokenActivityCursorBinding,
|
|
58
|
+
assertAdminTokenActivityEntry: () => assertAdminTokenActivityEntry,
|
|
59
|
+
assertAdminTokenActivityPage: () => assertAdminTokenActivityPage,
|
|
60
|
+
assertAdminTokenActivityPageForRequest: () => assertAdminTokenActivityPageForRequest,
|
|
61
|
+
assertAdminTokenActivityPageRequest: () => assertAdminTokenActivityPageRequest,
|
|
62
|
+
assertAdminTokenEconomySummary: () => assertAdminTokenEconomySummary,
|
|
63
|
+
assertAdminTokenTrendRequest: () => assertAdminTokenTrendRequest,
|
|
64
|
+
assertAdminTokenTrendResult: () => assertAdminTokenTrendResult,
|
|
65
|
+
assertAdminTokenTrendResultForRequest: () => assertAdminTokenTrendResultForRequest,
|
|
66
|
+
assertAdminTokenWalletBalanceCursorBinding: () => assertAdminTokenWalletBalanceCursorBinding,
|
|
67
|
+
assertAdminTokenWalletBalancePage: () => assertAdminTokenWalletBalancePage,
|
|
68
|
+
assertAdminTokenWalletBalancePageForRequest: () => assertAdminTokenWalletBalancePageForRequest,
|
|
69
|
+
assertAdminTokenWalletBalancePageRequest: () => assertAdminTokenWalletBalancePageRequest,
|
|
50
70
|
assertAuditedEconomyCommandEnvelope: () => assertAuditedEconomyCommandEnvelope,
|
|
51
71
|
assertBalancedTransaction: () => assertBalancedTransaction,
|
|
52
72
|
assertDeterministicWalletBalanceSummary: () => assertDeterministicWalletBalanceSummary,
|
|
@@ -176,6 +196,9 @@ __export(index_exports, {
|
|
|
176
196
|
canonicalTransactionPayload: () => canonicalTransactionPayload,
|
|
177
197
|
closeModuleAllowance: () => closeModuleAllowance,
|
|
178
198
|
convertRewardPayout: () => convertRewardPayout,
|
|
199
|
+
createAdminTokenAnomalyIndicator: () => createAdminTokenAnomalyIndicator,
|
|
200
|
+
createAdminTokenAnomalyUnavailable: () => createAdminTokenAnomalyUnavailable,
|
|
201
|
+
createDefaultAdminTokenReportingWindow: () => createDefaultAdminTokenReportingWindow,
|
|
179
202
|
createEarlyBackerRetentionFromPaidLot: () => createEarlyBackerRetentionFromPaidLot,
|
|
180
203
|
createEconomyPortableCustomerReceipt: () => createEconomyPortableCustomerReceipt,
|
|
181
204
|
createEconomyRecoveryAcceptanceEnvelope: () => createEconomyRecoveryAcceptanceEnvelope,
|
|
@@ -736,6 +759,1155 @@ function mapBitLabsConversionState(state) {
|
|
|
736
759
|
return transition;
|
|
737
760
|
}
|
|
738
761
|
|
|
762
|
+
// src/admin-reporting.ts
|
|
763
|
+
var ADMIN_TOKEN_DEFAULT_WINDOW_DAYS = 30;
|
|
764
|
+
var ADMIN_TOKEN_MAXIMUM_WINDOW_DAYS = 365;
|
|
765
|
+
var ADMIN_TOKEN_MAXIMUM_HOURLY_WINDOW_DAYS = 31;
|
|
766
|
+
var ADMIN_TOKEN_MAXIMUM_PAGE_SIZE = 100;
|
|
767
|
+
var ADMIN_TOKEN_MAXIMUM_TREND_POINTS = ADMIN_TOKEN_MAXIMUM_HOURLY_WINDOW_DAYS * 24 * 5;
|
|
768
|
+
var ADMIN_TOKEN_MINIMUM_COHORT_SIZE = 5;
|
|
769
|
+
var ADMIN_TOKEN_ANOMALY_BASELINE_DAYS = 28;
|
|
770
|
+
var DAY_MILLISECONDS = 864e5;
|
|
771
|
+
var HOUR_MILLISECONDS = 36e5;
|
|
772
|
+
var ACTIVITY_TYPES = /* @__PURE__ */ new Set([
|
|
773
|
+
"acquisition",
|
|
774
|
+
"spend",
|
|
775
|
+
"reversal",
|
|
776
|
+
"hold",
|
|
777
|
+
"failure"
|
|
778
|
+
]);
|
|
779
|
+
var ACTIVITY_STATUSES = /* @__PURE__ */ new Set([
|
|
780
|
+
"pending",
|
|
781
|
+
"held",
|
|
782
|
+
"settled",
|
|
783
|
+
"reversed",
|
|
784
|
+
"failed"
|
|
785
|
+
]);
|
|
786
|
+
var ACTIVITY_SOURCES = /* @__PURE__ */ new Set([
|
|
787
|
+
"paid-purchase",
|
|
788
|
+
"subscription",
|
|
789
|
+
"rewarded-activity",
|
|
790
|
+
"gameplay",
|
|
791
|
+
"system-adjustment",
|
|
792
|
+
"unknown"
|
|
793
|
+
]);
|
|
794
|
+
var SAFE_LABELS = /* @__PURE__ */ new Set([
|
|
795
|
+
"token-acquisition",
|
|
796
|
+
"token-spend",
|
|
797
|
+
"token-reversal",
|
|
798
|
+
"token-hold",
|
|
799
|
+
"token-activity-failed",
|
|
800
|
+
"token-system-adjustment",
|
|
801
|
+
"token-activity-unclassified"
|
|
802
|
+
]);
|
|
803
|
+
var SAFE_LABELS_BY_ACTIVITY_TYPE = {
|
|
804
|
+
acquisition: /* @__PURE__ */ new Set([
|
|
805
|
+
"token-acquisition",
|
|
806
|
+
"token-system-adjustment",
|
|
807
|
+
"token-activity-unclassified"
|
|
808
|
+
]),
|
|
809
|
+
spend: /* @__PURE__ */ new Set([
|
|
810
|
+
"token-spend",
|
|
811
|
+
"token-system-adjustment",
|
|
812
|
+
"token-activity-unclassified"
|
|
813
|
+
]),
|
|
814
|
+
reversal: /* @__PURE__ */ new Set([
|
|
815
|
+
"token-reversal",
|
|
816
|
+
"token-system-adjustment",
|
|
817
|
+
"token-activity-unclassified"
|
|
818
|
+
]),
|
|
819
|
+
hold: /* @__PURE__ */ new Set([
|
|
820
|
+
"token-hold",
|
|
821
|
+
"token-system-adjustment",
|
|
822
|
+
"token-activity-unclassified"
|
|
823
|
+
]),
|
|
824
|
+
failure: /* @__PURE__ */ new Set([
|
|
825
|
+
"token-activity-failed",
|
|
826
|
+
"token-activity-unclassified"
|
|
827
|
+
])
|
|
828
|
+
};
|
|
829
|
+
var ACTIVITY_SORTS = /* @__PURE__ */ new Set([
|
|
830
|
+
"occurred-at-desc",
|
|
831
|
+
"amount-absolute-desc"
|
|
832
|
+
]);
|
|
833
|
+
var PSEUDONYM_AUDIENCES = /* @__PURE__ */ new Set([
|
|
834
|
+
"admin-token-activity",
|
|
835
|
+
"mcp-token-activity"
|
|
836
|
+
]);
|
|
837
|
+
var BALANCE_PSEUDONYM_AUDIENCES = /* @__PURE__ */ new Set([
|
|
838
|
+
"admin-token-balances",
|
|
839
|
+
"mcp-token-balances"
|
|
840
|
+
]);
|
|
841
|
+
var WALLET_COMPONENTS = /* @__PURE__ */ new Set([
|
|
842
|
+
"household",
|
|
843
|
+
"personal",
|
|
844
|
+
"gameplay-allocation"
|
|
845
|
+
]);
|
|
846
|
+
var WALLET_STATUSES = /* @__PURE__ */ new Set([
|
|
847
|
+
"active",
|
|
848
|
+
"closed"
|
|
849
|
+
]);
|
|
850
|
+
var WALLET_BALANCE_SORTS = /* @__PURE__ */ new Set([
|
|
851
|
+
"available-desc",
|
|
852
|
+
"updated-at-desc"
|
|
853
|
+
]);
|
|
854
|
+
var TREND_GRANULARITIES = /* @__PURE__ */ new Set([
|
|
855
|
+
"hour",
|
|
856
|
+
"day"
|
|
857
|
+
]);
|
|
858
|
+
var ALIAS = /^[A-Za-z0-9_-]{16,96}$/u;
|
|
859
|
+
var OPAQUE_CURSOR = /^c1\.[A-Za-z0-9_-]{32,480}$/u;
|
|
860
|
+
var PSEUDONYM_VERSION = /^[A-Za-z0-9][A-Za-z0-9._-]{0,31}$/u;
|
|
861
|
+
var EXACT_STATISTIC_INTEGER = /^(?:0|-?[1-9][0-9]*)$/u;
|
|
862
|
+
var POSITIVE_UNSIGNED_INTEGER = /^[1-9][0-9]*$/u;
|
|
863
|
+
var MAXIMUM_STATISTIC_HALF_SUBUNITS = (TOKEN_SUBUNITS_MAX - TOKEN_SUBUNITS_MIN) * 2n;
|
|
864
|
+
var ANOMALY_UNAVAILABLE_REASONS = /* @__PURE__ */ new Set([
|
|
865
|
+
"insufficient-history",
|
|
866
|
+
"privacy-suppressed-baseline"
|
|
867
|
+
]);
|
|
868
|
+
function assertPlainObject(value, label) {
|
|
869
|
+
economyAssert(
|
|
870
|
+
typeof value === "object" && value !== null && !Array.isArray(value),
|
|
871
|
+
"INVALID_CONTRACT",
|
|
872
|
+
`${label} must be an object`
|
|
873
|
+
);
|
|
874
|
+
const prototype = Object.getPrototypeOf(value);
|
|
875
|
+
economyAssert(
|
|
876
|
+
(prototype === Object.prototype || prototype === null) && !Reflect.has(value, "toJSON"),
|
|
877
|
+
"INVALID_CONTRACT",
|
|
878
|
+
`${label} must be a plain data object without serialization hooks`
|
|
879
|
+
);
|
|
880
|
+
}
|
|
881
|
+
function assertExactKeys(value, allowedKeys, label) {
|
|
882
|
+
assertPlainObject(value, label);
|
|
883
|
+
const allowed = new Set(allowedKeys);
|
|
884
|
+
const keys = Reflect.ownKeys(value);
|
|
885
|
+
economyAssert(
|
|
886
|
+
allowedKeys.every(
|
|
887
|
+
(key) => !Reflect.has(value, key) || Object.hasOwn(value, key)
|
|
888
|
+
) && keys.every((key) => {
|
|
889
|
+
if (typeof key !== "string" || !allowed.has(key)) {
|
|
890
|
+
return false;
|
|
891
|
+
}
|
|
892
|
+
const descriptor = Object.getOwnPropertyDescriptor(value, key);
|
|
893
|
+
return descriptor !== void 0 && descriptor.enumerable && "value" in descriptor;
|
|
894
|
+
}),
|
|
895
|
+
"INVALID_CONTRACT",
|
|
896
|
+
`${label} contains an unsupported, identifying, or non-data property`
|
|
897
|
+
);
|
|
898
|
+
}
|
|
899
|
+
function assertAlias(value, label) {
|
|
900
|
+
economyAssert(
|
|
901
|
+
typeof value === "string" && ALIAS.test(value),
|
|
902
|
+
"INVALID_CONTRACT",
|
|
903
|
+
`${label} must be an opaque pseudonymous alias`
|
|
904
|
+
);
|
|
905
|
+
}
|
|
906
|
+
function assertOpaqueCursor(value) {
|
|
907
|
+
economyAssert(
|
|
908
|
+
typeof value === "string" && OPAQUE_CURSOR.test(value),
|
|
909
|
+
"INVALID_CONTRACT",
|
|
910
|
+
"Admin Token cursor must be a bounded confidentiality-protected opaque value"
|
|
911
|
+
);
|
|
912
|
+
}
|
|
913
|
+
function assertUniqueValues(values, allowed, label) {
|
|
914
|
+
economyAssert(
|
|
915
|
+
Array.isArray(values),
|
|
916
|
+
"INVALID_CONTRACT",
|
|
917
|
+
`${label} must be a list`
|
|
918
|
+
);
|
|
919
|
+
const unique = new Set(values);
|
|
920
|
+
economyAssert(
|
|
921
|
+
values.length > 0 && values.length === unique.size && values.every((value) => allowed.has(value)),
|
|
922
|
+
"INVALID_CONTRACT",
|
|
923
|
+
`${label} must contain unique supported values`
|
|
924
|
+
);
|
|
925
|
+
}
|
|
926
|
+
function absolute(value) {
|
|
927
|
+
return value < 0n ? -value : value;
|
|
928
|
+
}
|
|
929
|
+
function compareTextDescending(left, right) {
|
|
930
|
+
if (left === right) {
|
|
931
|
+
return 0;
|
|
932
|
+
}
|
|
933
|
+
return left > right ? -1 : 1;
|
|
934
|
+
}
|
|
935
|
+
function assertReportingWindow(window, maximumDays = ADMIN_TOKEN_MAXIMUM_WINDOW_DAYS) {
|
|
936
|
+
assertExactKeys(
|
|
937
|
+
window,
|
|
938
|
+
["fromInclusive", "toExclusive"],
|
|
939
|
+
"Admin Token reporting window"
|
|
940
|
+
);
|
|
941
|
+
const from = parseIsoTimestamp(window.fromInclusive);
|
|
942
|
+
const to = parseIsoTimestamp(window.toExclusive);
|
|
943
|
+
economyAssert(
|
|
944
|
+
from < to && to - from <= maximumDays * DAY_MILLISECONDS,
|
|
945
|
+
"INVALID_TIME_WINDOW",
|
|
946
|
+
`Admin Token reporting window must be positive and no longer than ${maximumDays} days`
|
|
947
|
+
);
|
|
948
|
+
return { from, to };
|
|
949
|
+
}
|
|
950
|
+
function createDefaultAdminTokenReportingWindow(asOf) {
|
|
951
|
+
const to = parseIsoTimestamp(asOf);
|
|
952
|
+
return {
|
|
953
|
+
fromInclusive: new Date(
|
|
954
|
+
to - ADMIN_TOKEN_DEFAULT_WINDOW_DAYS * DAY_MILLISECONDS
|
|
955
|
+
).toISOString(),
|
|
956
|
+
toExclusive: new Date(to).toISOString()
|
|
957
|
+
};
|
|
958
|
+
}
|
|
959
|
+
function assertNonNegativeTokenAmounts(amounts, label) {
|
|
960
|
+
economyAssert(
|
|
961
|
+
amounts.every((amount) => parseTokenSubunits(amount) >= 0n),
|
|
962
|
+
"INVALID_AMOUNT",
|
|
963
|
+
`${label} cannot contain a negative amount`
|
|
964
|
+
);
|
|
965
|
+
}
|
|
966
|
+
function assertPositiveAuthoritySequence(sequence, label) {
|
|
967
|
+
economyAssert(
|
|
968
|
+
typeof sequence === "string" && POSITIVE_UNSIGNED_INTEGER.test(sequence),
|
|
969
|
+
"INVALID_CONTRACT",
|
|
970
|
+
`${label} must be a canonical positive integer`
|
|
971
|
+
);
|
|
972
|
+
}
|
|
973
|
+
function assertAdminTokenEconomySummary(summary) {
|
|
974
|
+
assertExactKeys(
|
|
975
|
+
summary,
|
|
976
|
+
[
|
|
977
|
+
"schemaVersion",
|
|
978
|
+
"generatedAt",
|
|
979
|
+
"projectionAsOf",
|
|
980
|
+
"authoritySequence",
|
|
981
|
+
"walletCount",
|
|
982
|
+
"activeWalletCount",
|
|
983
|
+
"balances",
|
|
984
|
+
"lifetime",
|
|
985
|
+
"rawIdentifiersIncluded"
|
|
986
|
+
],
|
|
987
|
+
"Admin Token economy summary"
|
|
988
|
+
);
|
|
989
|
+
assertExactKeys(
|
|
990
|
+
summary.balances,
|
|
991
|
+
["schemaVersion", "available", "reserved", "held", "rewardProgress"],
|
|
992
|
+
"Admin Token aggregate balances"
|
|
993
|
+
);
|
|
994
|
+
assertExactKeys(
|
|
995
|
+
summary.lifetime,
|
|
996
|
+
[
|
|
997
|
+
"schemaVersion",
|
|
998
|
+
"bought",
|
|
999
|
+
"earned",
|
|
1000
|
+
"allocated",
|
|
1001
|
+
"reclaimed",
|
|
1002
|
+
"spent",
|
|
1003
|
+
"reversed"
|
|
1004
|
+
],
|
|
1005
|
+
"Admin Token aggregate lifetime"
|
|
1006
|
+
);
|
|
1007
|
+
economyAssert(
|
|
1008
|
+
summary.schemaVersion === ECONOMY_CONTRACT_VERSION && summary.balances.schemaVersion === ECONOMY_CONTRACT_VERSION && summary.lifetime.schemaVersion === ECONOMY_CONTRACT_VERSION && summary.rawIdentifiersIncluded === false && Number.isSafeInteger(summary.walletCount) && summary.walletCount >= 0 && Number.isSafeInteger(summary.activeWalletCount) && summary.activeWalletCount >= 0 && summary.activeWalletCount <= summary.walletCount,
|
|
1009
|
+
"INVALID_CONTRACT",
|
|
1010
|
+
"Admin Token economy summary metadata is invalid"
|
|
1011
|
+
);
|
|
1012
|
+
const generatedAt = parseIsoTimestamp(summary.generatedAt);
|
|
1013
|
+
const projectionAsOf = parseIsoTimestamp(summary.projectionAsOf);
|
|
1014
|
+
economyAssert(
|
|
1015
|
+
projectionAsOf <= generatedAt,
|
|
1016
|
+
"INVALID_TIME_WINDOW",
|
|
1017
|
+
"Admin Token projection cannot be newer than its generated result"
|
|
1018
|
+
);
|
|
1019
|
+
assertPositiveAuthoritySequence(
|
|
1020
|
+
summary.authoritySequence,
|
|
1021
|
+
"Admin Token summary authority sequence"
|
|
1022
|
+
);
|
|
1023
|
+
assertNonNegativeTokenAmounts(
|
|
1024
|
+
[
|
|
1025
|
+
summary.balances.available,
|
|
1026
|
+
summary.balances.reserved,
|
|
1027
|
+
summary.balances.held,
|
|
1028
|
+
summary.balances.rewardProgress,
|
|
1029
|
+
summary.lifetime.bought,
|
|
1030
|
+
summary.lifetime.earned,
|
|
1031
|
+
summary.lifetime.allocated,
|
|
1032
|
+
summary.lifetime.reclaimed,
|
|
1033
|
+
summary.lifetime.spent,
|
|
1034
|
+
summary.lifetime.reversed
|
|
1035
|
+
],
|
|
1036
|
+
"Admin Token economy summary"
|
|
1037
|
+
);
|
|
1038
|
+
}
|
|
1039
|
+
function assertAdminTokenWalletBalanceFilter(filter) {
|
|
1040
|
+
assertExactKeys(
|
|
1041
|
+
filter,
|
|
1042
|
+
["components", "statuses", "subjectAlias"],
|
|
1043
|
+
"Admin Token wallet balance filter"
|
|
1044
|
+
);
|
|
1045
|
+
if (filter.components !== void 0) {
|
|
1046
|
+
assertUniqueValues(
|
|
1047
|
+
filter.components,
|
|
1048
|
+
WALLET_COMPONENTS,
|
|
1049
|
+
"Admin Token wallet components"
|
|
1050
|
+
);
|
|
1051
|
+
}
|
|
1052
|
+
if (filter.statuses !== void 0) {
|
|
1053
|
+
assertUniqueValues(
|
|
1054
|
+
filter.statuses,
|
|
1055
|
+
WALLET_STATUSES,
|
|
1056
|
+
"Admin Token wallet statuses"
|
|
1057
|
+
);
|
|
1058
|
+
}
|
|
1059
|
+
if (filter.subjectAlias !== void 0) {
|
|
1060
|
+
assertAlias(filter.subjectAlias, "Wallet subject alias filter");
|
|
1061
|
+
}
|
|
1062
|
+
}
|
|
1063
|
+
function sameWalletBalanceFilter(left, right) {
|
|
1064
|
+
if (left === void 0 || right === void 0) {
|
|
1065
|
+
return left === right;
|
|
1066
|
+
}
|
|
1067
|
+
return sameOptionalValues(left.components, right.components) && sameOptionalValues(left.statuses, right.statuses) && left.subjectAlias === right.subjectAlias;
|
|
1068
|
+
}
|
|
1069
|
+
function assertAdminTokenWalletBalanceCursorBinding(binding) {
|
|
1070
|
+
assertExactKeys(
|
|
1071
|
+
binding,
|
|
1072
|
+
[
|
|
1073
|
+
"schemaVersion",
|
|
1074
|
+
"sort",
|
|
1075
|
+
"filter",
|
|
1076
|
+
"audience",
|
|
1077
|
+
"pseudonymVersion"
|
|
1078
|
+
],
|
|
1079
|
+
"Admin Token wallet balance cursor binding"
|
|
1080
|
+
);
|
|
1081
|
+
economyAssert(
|
|
1082
|
+
binding.schemaVersion === ECONOMY_CONTRACT_VERSION && WALLET_BALANCE_SORTS.has(binding.sort) && BALANCE_PSEUDONYM_AUDIENCES.has(binding.audience) && PSEUDONYM_VERSION.test(binding.pseudonymVersion),
|
|
1083
|
+
"INVALID_CONTRACT",
|
|
1084
|
+
"Unsupported Admin Token wallet balance cursor binding"
|
|
1085
|
+
);
|
|
1086
|
+
if (binding.filter !== void 0) {
|
|
1087
|
+
assertAdminTokenWalletBalanceFilter(binding.filter);
|
|
1088
|
+
}
|
|
1089
|
+
}
|
|
1090
|
+
function assertAdminTokenWalletBalancePageRequest(request) {
|
|
1091
|
+
assertExactKeys(
|
|
1092
|
+
request,
|
|
1093
|
+
[
|
|
1094
|
+
"schemaVersion",
|
|
1095
|
+
"limit",
|
|
1096
|
+
"cursor",
|
|
1097
|
+
"cursorBinding",
|
|
1098
|
+
"sort",
|
|
1099
|
+
"filter",
|
|
1100
|
+
"audience",
|
|
1101
|
+
"pseudonymVersion"
|
|
1102
|
+
],
|
|
1103
|
+
"Admin Token wallet balance request"
|
|
1104
|
+
);
|
|
1105
|
+
economyAssert(
|
|
1106
|
+
request.schemaVersion === ECONOMY_CONTRACT_VERSION && Number.isSafeInteger(request.limit) && request.limit >= 1 && request.limit <= ADMIN_TOKEN_MAXIMUM_PAGE_SIZE && WALLET_BALANCE_SORTS.has(request.sort) && BALANCE_PSEUDONYM_AUDIENCES.has(request.audience) && PSEUDONYM_VERSION.test(request.pseudonymVersion),
|
|
1107
|
+
"INVALID_CONTRACT",
|
|
1108
|
+
"Unsupported or unbounded Admin Token wallet balance request"
|
|
1109
|
+
);
|
|
1110
|
+
if (request.filter !== void 0) {
|
|
1111
|
+
assertAdminTokenWalletBalanceFilter(request.filter);
|
|
1112
|
+
}
|
|
1113
|
+
economyAssert(
|
|
1114
|
+
request.cursor === void 0 === (request.cursorBinding === void 0),
|
|
1115
|
+
"INVALID_CONTRACT",
|
|
1116
|
+
"Admin Token wallet balance cursor and binding must be provided together"
|
|
1117
|
+
);
|
|
1118
|
+
if (request.cursor === void 0 || request.cursorBinding === void 0) {
|
|
1119
|
+
return;
|
|
1120
|
+
}
|
|
1121
|
+
assertOpaqueCursor(request.cursor);
|
|
1122
|
+
assertAdminTokenWalletBalanceCursorBinding(request.cursorBinding);
|
|
1123
|
+
economyAssert(
|
|
1124
|
+
request.cursorBinding.sort === request.sort && request.cursorBinding.audience === request.audience && request.cursorBinding.pseudonymVersion === request.pseudonymVersion && sameWalletBalanceFilter(request.cursorBinding.filter, request.filter),
|
|
1125
|
+
"INVALID_CONTRACT",
|
|
1126
|
+
"Admin Token wallet balance cursor is not bound to the normalized query"
|
|
1127
|
+
);
|
|
1128
|
+
}
|
|
1129
|
+
function assertAdminTokenWalletBalanceEntry(entry) {
|
|
1130
|
+
assertExactKeys(
|
|
1131
|
+
entry,
|
|
1132
|
+
[
|
|
1133
|
+
"schemaVersion",
|
|
1134
|
+
"walletAlias",
|
|
1135
|
+
"subjectAlias",
|
|
1136
|
+
"component",
|
|
1137
|
+
"status",
|
|
1138
|
+
"available",
|
|
1139
|
+
"reserved",
|
|
1140
|
+
"held",
|
|
1141
|
+
"rewardProgress",
|
|
1142
|
+
"updatedAt",
|
|
1143
|
+
"authoritySequence"
|
|
1144
|
+
],
|
|
1145
|
+
"Admin Token wallet balance entry"
|
|
1146
|
+
);
|
|
1147
|
+
economyAssert(
|
|
1148
|
+
entry.schemaVersion === ECONOMY_CONTRACT_VERSION && WALLET_COMPONENTS.has(entry.component) && WALLET_STATUSES.has(entry.status),
|
|
1149
|
+
"INVALID_CONTRACT",
|
|
1150
|
+
"Unsupported Admin Token wallet balance entry"
|
|
1151
|
+
);
|
|
1152
|
+
assertAlias(entry.walletAlias, "Wallet alias");
|
|
1153
|
+
assertAlias(entry.subjectAlias, "Wallet subject alias");
|
|
1154
|
+
economyAssert(
|
|
1155
|
+
entry.walletAlias !== entry.subjectAlias,
|
|
1156
|
+
"INVALID_CONTRACT",
|
|
1157
|
+
"Wallet and subject aliases must use separate pseudonym domains"
|
|
1158
|
+
);
|
|
1159
|
+
assertNonNegativeTokenAmounts(
|
|
1160
|
+
[entry.available, entry.reserved, entry.held, entry.rewardProgress],
|
|
1161
|
+
"Admin Token wallet balance entry"
|
|
1162
|
+
);
|
|
1163
|
+
parseIsoTimestamp(entry.updatedAt);
|
|
1164
|
+
assertPositiveAuthoritySequence(
|
|
1165
|
+
entry.authoritySequence,
|
|
1166
|
+
"Admin Token wallet balance authority sequence"
|
|
1167
|
+
);
|
|
1168
|
+
}
|
|
1169
|
+
function compareWalletBalanceEntries(left, right, sort) {
|
|
1170
|
+
if (sort === "available-desc") {
|
|
1171
|
+
const leftAvailable = parseTokenSubunits(left.available);
|
|
1172
|
+
const rightAvailable = parseTokenSubunits(right.available);
|
|
1173
|
+
if (leftAvailable !== rightAvailable) {
|
|
1174
|
+
return leftAvailable > rightAvailable ? -1 : 1;
|
|
1175
|
+
}
|
|
1176
|
+
}
|
|
1177
|
+
const leftUpdatedAt = parseIsoTimestamp(left.updatedAt);
|
|
1178
|
+
const rightUpdatedAt = parseIsoTimestamp(right.updatedAt);
|
|
1179
|
+
if (leftUpdatedAt !== rightUpdatedAt) {
|
|
1180
|
+
return leftUpdatedAt > rightUpdatedAt ? -1 : 1;
|
|
1181
|
+
}
|
|
1182
|
+
return compareTextDescending(left.walletAlias, right.walletAlias);
|
|
1183
|
+
}
|
|
1184
|
+
function assertAdminTokenWalletBalancePage(page) {
|
|
1185
|
+
assertExactKeys(
|
|
1186
|
+
page,
|
|
1187
|
+
["schemaVersion", "entries", "hasMore", "nextCursor", "metadata"],
|
|
1188
|
+
"Admin Token wallet balance page"
|
|
1189
|
+
);
|
|
1190
|
+
assertExactKeys(
|
|
1191
|
+
page.metadata,
|
|
1192
|
+
[
|
|
1193
|
+
"schemaVersion",
|
|
1194
|
+
"generatedAt",
|
|
1195
|
+
"sort",
|
|
1196
|
+
"filter",
|
|
1197
|
+
"pageLimit",
|
|
1198
|
+
"audience",
|
|
1199
|
+
"pseudonymVersion",
|
|
1200
|
+
"rawIdentifiersIncluded"
|
|
1201
|
+
],
|
|
1202
|
+
"Admin Token wallet balance metadata"
|
|
1203
|
+
);
|
|
1204
|
+
economyAssert(
|
|
1205
|
+
page.schemaVersion === ECONOMY_CONTRACT_VERSION && page.metadata.schemaVersion === ECONOMY_CONTRACT_VERSION && typeof page.hasMore === "boolean" && page.metadata.rawIdentifiersIncluded === false && WALLET_BALANCE_SORTS.has(page.metadata.sort) && BALANCE_PSEUDONYM_AUDIENCES.has(page.metadata.audience) && PSEUDONYM_VERSION.test(page.metadata.pseudonymVersion) && Number.isSafeInteger(page.metadata.pageLimit) && page.metadata.pageLimit >= 1 && page.metadata.pageLimit <= ADMIN_TOKEN_MAXIMUM_PAGE_SIZE && Array.isArray(page.entries) && page.entries.length <= page.metadata.pageLimit && page.hasMore === (page.nextCursor !== void 0) && (!page.hasMore || page.entries.length > 0),
|
|
1206
|
+
"INVALID_CONTRACT",
|
|
1207
|
+
"Unsupported or unbounded Admin Token wallet balance page"
|
|
1208
|
+
);
|
|
1209
|
+
if (page.metadata.filter !== void 0) {
|
|
1210
|
+
assertAdminTokenWalletBalanceFilter(page.metadata.filter);
|
|
1211
|
+
}
|
|
1212
|
+
parseIsoTimestamp(page.metadata.generatedAt);
|
|
1213
|
+
if (page.nextCursor !== void 0) {
|
|
1214
|
+
assertOpaqueCursor(page.nextCursor);
|
|
1215
|
+
}
|
|
1216
|
+
const walletAliases = /* @__PURE__ */ new Set();
|
|
1217
|
+
let previous;
|
|
1218
|
+
for (const entry of page.entries) {
|
|
1219
|
+
assertAdminTokenWalletBalanceEntry(entry);
|
|
1220
|
+
const filter = page.metadata.filter;
|
|
1221
|
+
economyAssert(
|
|
1222
|
+
filter === void 0 || (filter.components === void 0 || filter.components.includes(entry.component)) && (filter.statuses === void 0 || filter.statuses.includes(entry.status)) && (filter.subjectAlias === void 0 || filter.subjectAlias === entry.subjectAlias),
|
|
1223
|
+
"INVALID_CONTRACT",
|
|
1224
|
+
"Admin Token wallet balance result contains an unrequested row"
|
|
1225
|
+
);
|
|
1226
|
+
economyAssert(
|
|
1227
|
+
!walletAliases.has(entry.walletAlias),
|
|
1228
|
+
"DUPLICATE_IDENTIFIER",
|
|
1229
|
+
"Admin Token wallet balance page cannot repeat a wallet alias"
|
|
1230
|
+
);
|
|
1231
|
+
walletAliases.add(entry.walletAlias);
|
|
1232
|
+
if (previous !== void 0) {
|
|
1233
|
+
economyAssert(
|
|
1234
|
+
compareWalletBalanceEntries(previous, entry, page.metadata.sort) < 0,
|
|
1235
|
+
"INVALID_CONTRACT",
|
|
1236
|
+
"Admin Token wallet balance page does not use its declared stable sort"
|
|
1237
|
+
);
|
|
1238
|
+
}
|
|
1239
|
+
previous = entry;
|
|
1240
|
+
}
|
|
1241
|
+
}
|
|
1242
|
+
function assertAdminTokenWalletBalancePageForRequest(page, request) {
|
|
1243
|
+
assertAdminTokenWalletBalancePageRequest(request);
|
|
1244
|
+
assertAdminTokenWalletBalancePage(page);
|
|
1245
|
+
economyAssert(
|
|
1246
|
+
page.metadata.sort === request.sort && sameWalletBalanceFilter(page.metadata.filter, request.filter) && page.metadata.pageLimit === request.limit && page.metadata.audience === request.audience && page.metadata.pseudonymVersion === request.pseudonymVersion,
|
|
1247
|
+
"INVALID_CONTRACT",
|
|
1248
|
+
"Admin Token wallet balance result does not match its normalized request"
|
|
1249
|
+
);
|
|
1250
|
+
}
|
|
1251
|
+
function assertAdminTokenActivityEntry(entry) {
|
|
1252
|
+
assertExactKeys(
|
|
1253
|
+
entry,
|
|
1254
|
+
[
|
|
1255
|
+
"schemaVersion",
|
|
1256
|
+
"occurredAt",
|
|
1257
|
+
"activityType",
|
|
1258
|
+
"status",
|
|
1259
|
+
"source",
|
|
1260
|
+
"amount",
|
|
1261
|
+
"safeLabel",
|
|
1262
|
+
"rowAlias",
|
|
1263
|
+
"subjectAlias"
|
|
1264
|
+
],
|
|
1265
|
+
"Admin Token activity entry"
|
|
1266
|
+
);
|
|
1267
|
+
economyAssert(
|
|
1268
|
+
entry.schemaVersion === ECONOMY_CONTRACT_VERSION && ACTIVITY_TYPES.has(entry.activityType) && ACTIVITY_STATUSES.has(entry.status) && ACTIVITY_SOURCES.has(entry.source),
|
|
1269
|
+
"INVALID_CONTRACT",
|
|
1270
|
+
"Unsupported Admin Token activity contract"
|
|
1271
|
+
);
|
|
1272
|
+
parseIsoTimestamp(entry.occurredAt);
|
|
1273
|
+
const amount = parseTokenSubunits(entry.amount);
|
|
1274
|
+
economyAssert(
|
|
1275
|
+
(amount !== 0n || entry.activityType === "failure") && (entry.activityType !== "acquisition" || amount > 0n) && (entry.activityType !== "spend" || amount < 0n),
|
|
1276
|
+
"INVALID_AMOUNT",
|
|
1277
|
+
"Admin Token activity amount has an invalid sign or zero value"
|
|
1278
|
+
);
|
|
1279
|
+
economyAssert(
|
|
1280
|
+
entry.activityType === "failure" === (entry.status === "failed"),
|
|
1281
|
+
"INVALID_CONTRACT",
|
|
1282
|
+
"Failed rows must use the failure activity type"
|
|
1283
|
+
);
|
|
1284
|
+
economyAssert(
|
|
1285
|
+
SAFE_LABELS.has(entry.safeLabel) && SAFE_LABELS_BY_ACTIVITY_TYPE[entry.activityType]?.has(entry.safeLabel) === true,
|
|
1286
|
+
"INVALID_CONTRACT",
|
|
1287
|
+
"Admin Token activity label must use the approved non-identifying allowlist"
|
|
1288
|
+
);
|
|
1289
|
+
assertAlias(entry.rowAlias, "Row alias");
|
|
1290
|
+
assertAlias(entry.subjectAlias, "Subject alias");
|
|
1291
|
+
economyAssert(
|
|
1292
|
+
entry.rowAlias !== entry.subjectAlias,
|
|
1293
|
+
"INVALID_CONTRACT",
|
|
1294
|
+
"Row and subject aliases must use separate pseudonym domains"
|
|
1295
|
+
);
|
|
1296
|
+
}
|
|
1297
|
+
function assertAdminTokenActivityFilter(filter) {
|
|
1298
|
+
assertExactKeys(
|
|
1299
|
+
filter,
|
|
1300
|
+
[
|
|
1301
|
+
"activityTypes",
|
|
1302
|
+
"statuses",
|
|
1303
|
+
"sources",
|
|
1304
|
+
"subjectAlias"
|
|
1305
|
+
],
|
|
1306
|
+
"Admin Token activity filter"
|
|
1307
|
+
);
|
|
1308
|
+
if (filter.activityTypes !== void 0) {
|
|
1309
|
+
assertUniqueValues(
|
|
1310
|
+
filter.activityTypes,
|
|
1311
|
+
ACTIVITY_TYPES,
|
|
1312
|
+
"Admin Token activity types"
|
|
1313
|
+
);
|
|
1314
|
+
}
|
|
1315
|
+
if (filter.statuses !== void 0) {
|
|
1316
|
+
assertUniqueValues(
|
|
1317
|
+
filter.statuses,
|
|
1318
|
+
ACTIVITY_STATUSES,
|
|
1319
|
+
"Admin Token activity statuses"
|
|
1320
|
+
);
|
|
1321
|
+
}
|
|
1322
|
+
if (filter.sources !== void 0) {
|
|
1323
|
+
assertUniqueValues(
|
|
1324
|
+
filter.sources,
|
|
1325
|
+
ACTIVITY_SOURCES,
|
|
1326
|
+
"Admin Token activity sources"
|
|
1327
|
+
);
|
|
1328
|
+
}
|
|
1329
|
+
if (filter.subjectAlias !== void 0) {
|
|
1330
|
+
assertAlias(filter.subjectAlias, "Subject alias filter");
|
|
1331
|
+
}
|
|
1332
|
+
}
|
|
1333
|
+
function sameOptionalValues(left, right) {
|
|
1334
|
+
if (left === void 0 || right === void 0) {
|
|
1335
|
+
return left === right;
|
|
1336
|
+
}
|
|
1337
|
+
return left.length === right.length && left.every((value) => right.includes(value));
|
|
1338
|
+
}
|
|
1339
|
+
function sameActivityFilter(left, right) {
|
|
1340
|
+
if (left === void 0 || right === void 0) {
|
|
1341
|
+
return left === right;
|
|
1342
|
+
}
|
|
1343
|
+
return sameOptionalValues(left.activityTypes, right.activityTypes) && sameOptionalValues(left.statuses, right.statuses) && sameOptionalValues(left.sources, right.sources) && left.subjectAlias === right.subjectAlias;
|
|
1344
|
+
}
|
|
1345
|
+
function assertAdminTokenActivityCursorBinding(binding) {
|
|
1346
|
+
assertExactKeys(
|
|
1347
|
+
binding,
|
|
1348
|
+
[
|
|
1349
|
+
"schemaVersion",
|
|
1350
|
+
"sort",
|
|
1351
|
+
"window",
|
|
1352
|
+
"filter",
|
|
1353
|
+
"audience",
|
|
1354
|
+
"pseudonymVersion"
|
|
1355
|
+
],
|
|
1356
|
+
"Admin Token activity cursor binding"
|
|
1357
|
+
);
|
|
1358
|
+
economyAssert(
|
|
1359
|
+
binding.schemaVersion === ECONOMY_CONTRACT_VERSION && ACTIVITY_SORTS.has(binding.sort) && PSEUDONYM_AUDIENCES.has(binding.audience) && PSEUDONYM_VERSION.test(binding.pseudonymVersion),
|
|
1360
|
+
"INVALID_CONTRACT",
|
|
1361
|
+
"Unsupported Admin Token activity cursor binding"
|
|
1362
|
+
);
|
|
1363
|
+
assertReportingWindow(binding.window);
|
|
1364
|
+
if (binding.filter !== void 0) {
|
|
1365
|
+
assertAdminTokenActivityFilter(binding.filter);
|
|
1366
|
+
}
|
|
1367
|
+
}
|
|
1368
|
+
function assertAdminTokenActivityPageRequest(request) {
|
|
1369
|
+
assertExactKeys(
|
|
1370
|
+
request,
|
|
1371
|
+
[
|
|
1372
|
+
"schemaVersion",
|
|
1373
|
+
"limit",
|
|
1374
|
+
"cursor",
|
|
1375
|
+
"cursorBinding",
|
|
1376
|
+
"sort",
|
|
1377
|
+
"window",
|
|
1378
|
+
"filter",
|
|
1379
|
+
"audience",
|
|
1380
|
+
"pseudonymVersion"
|
|
1381
|
+
],
|
|
1382
|
+
"Admin Token activity request"
|
|
1383
|
+
);
|
|
1384
|
+
economyAssert(
|
|
1385
|
+
request.schemaVersion === ECONOMY_CONTRACT_VERSION && Number.isSafeInteger(request.limit) && request.limit >= 1 && request.limit <= ADMIN_TOKEN_MAXIMUM_PAGE_SIZE && ACTIVITY_SORTS.has(request.sort) && PSEUDONYM_AUDIENCES.has(request.audience) && PSEUDONYM_VERSION.test(request.pseudonymVersion),
|
|
1386
|
+
"INVALID_CONTRACT",
|
|
1387
|
+
"Unsupported or unbounded Admin Token activity request"
|
|
1388
|
+
);
|
|
1389
|
+
assertReportingWindow(request.window);
|
|
1390
|
+
if (request.filter !== void 0) {
|
|
1391
|
+
assertAdminTokenActivityFilter(request.filter);
|
|
1392
|
+
}
|
|
1393
|
+
economyAssert(
|
|
1394
|
+
request.cursor === void 0 === (request.cursorBinding === void 0),
|
|
1395
|
+
"INVALID_CONTRACT",
|
|
1396
|
+
"Admin Token activity cursor and trusted binding must be provided together"
|
|
1397
|
+
);
|
|
1398
|
+
if (request.cursor === void 0 || request.cursorBinding === void 0) {
|
|
1399
|
+
return;
|
|
1400
|
+
}
|
|
1401
|
+
assertOpaqueCursor(request.cursor);
|
|
1402
|
+
assertAdminTokenActivityCursorBinding(request.cursorBinding);
|
|
1403
|
+
economyAssert(
|
|
1404
|
+
request.cursorBinding.sort === request.sort && request.cursorBinding.window.fromInclusive === request.window.fromInclusive && request.cursorBinding.window.toExclusive === request.window.toExclusive && request.cursorBinding.audience === request.audience && request.cursorBinding.pseudonymVersion === request.pseudonymVersion && sameActivityFilter(request.cursorBinding.filter, request.filter),
|
|
1405
|
+
"INVALID_CONTRACT",
|
|
1406
|
+
"Admin Token cursor is not bound to the normalized query"
|
|
1407
|
+
);
|
|
1408
|
+
}
|
|
1409
|
+
function compareActivityEntries(left, right, sort) {
|
|
1410
|
+
if (sort === "amount-absolute-desc") {
|
|
1411
|
+
const leftAmount = absolute(parseTokenSubunits(left.amount));
|
|
1412
|
+
const rightAmount = absolute(parseTokenSubunits(right.amount));
|
|
1413
|
+
if (leftAmount !== rightAmount) {
|
|
1414
|
+
return leftAmount > rightAmount ? -1 : 1;
|
|
1415
|
+
}
|
|
1416
|
+
}
|
|
1417
|
+
const leftTime = parseIsoTimestamp(left.occurredAt);
|
|
1418
|
+
const rightTime = parseIsoTimestamp(right.occurredAt);
|
|
1419
|
+
if (leftTime !== rightTime) {
|
|
1420
|
+
return leftTime > rightTime ? -1 : 1;
|
|
1421
|
+
}
|
|
1422
|
+
return compareTextDescending(left.rowAlias, right.rowAlias);
|
|
1423
|
+
}
|
|
1424
|
+
function assertAdminTokenActivityPage(page) {
|
|
1425
|
+
assertExactKeys(
|
|
1426
|
+
page,
|
|
1427
|
+
["schemaVersion", "entries", "hasMore", "nextCursor", "metadata"],
|
|
1428
|
+
"Admin Token activity page"
|
|
1429
|
+
);
|
|
1430
|
+
assertExactKeys(
|
|
1431
|
+
page.metadata,
|
|
1432
|
+
[
|
|
1433
|
+
"schemaVersion",
|
|
1434
|
+
"generatedAt",
|
|
1435
|
+
"fromInclusive",
|
|
1436
|
+
"toExclusive",
|
|
1437
|
+
"sort",
|
|
1438
|
+
"filter",
|
|
1439
|
+
"pageLimit",
|
|
1440
|
+
"audience",
|
|
1441
|
+
"pseudonymVersion",
|
|
1442
|
+
"rawIdentifiersIncluded"
|
|
1443
|
+
],
|
|
1444
|
+
"Admin Token activity metadata"
|
|
1445
|
+
);
|
|
1446
|
+
economyAssert(
|
|
1447
|
+
page.schemaVersion === ECONOMY_CONTRACT_VERSION && page.metadata.schemaVersion === ECONOMY_CONTRACT_VERSION && typeof page.hasMore === "boolean" && page.metadata.rawIdentifiersIncluded === false && ACTIVITY_SORTS.has(page.metadata.sort) && PSEUDONYM_AUDIENCES.has(page.metadata.audience) && PSEUDONYM_VERSION.test(page.metadata.pseudonymVersion) && Number.isSafeInteger(page.metadata.pageLimit) && page.metadata.pageLimit >= 1 && page.metadata.pageLimit <= ADMIN_TOKEN_MAXIMUM_PAGE_SIZE,
|
|
1448
|
+
"INVALID_CONTRACT",
|
|
1449
|
+
"Unsupported Admin Token activity result metadata"
|
|
1450
|
+
);
|
|
1451
|
+
const window = assertReportingWindow({
|
|
1452
|
+
fromInclusive: page.metadata.fromInclusive,
|
|
1453
|
+
toExclusive: page.metadata.toExclusive
|
|
1454
|
+
});
|
|
1455
|
+
if (page.metadata.filter !== void 0) {
|
|
1456
|
+
assertAdminTokenActivityFilter(page.metadata.filter);
|
|
1457
|
+
}
|
|
1458
|
+
parseIsoTimestamp(page.metadata.generatedAt);
|
|
1459
|
+
economyAssert(
|
|
1460
|
+
Array.isArray(page.entries) && page.entries.length <= page.metadata.pageLimit && page.hasMore === (page.nextCursor !== void 0) && (!page.hasMore || page.entries.length > 0),
|
|
1461
|
+
"INVALID_CONTRACT",
|
|
1462
|
+
"Admin Token activity page is unbounded or has inconsistent pagination"
|
|
1463
|
+
);
|
|
1464
|
+
if (page.nextCursor !== void 0) {
|
|
1465
|
+
assertOpaqueCursor(page.nextCursor);
|
|
1466
|
+
}
|
|
1467
|
+
const rowAliases = /* @__PURE__ */ new Set();
|
|
1468
|
+
let previous;
|
|
1469
|
+
for (const entry of page.entries) {
|
|
1470
|
+
assertAdminTokenActivityEntry(entry);
|
|
1471
|
+
const occurredAt = parseIsoTimestamp(entry.occurredAt);
|
|
1472
|
+
economyAssert(
|
|
1473
|
+
occurredAt >= window.from && occurredAt < window.to,
|
|
1474
|
+
"INVALID_TIME_WINDOW",
|
|
1475
|
+
"Admin Token activity falls outside the declared result window"
|
|
1476
|
+
);
|
|
1477
|
+
const filter = page.metadata.filter;
|
|
1478
|
+
economyAssert(
|
|
1479
|
+
filter === void 0 || (filter.activityTypes === void 0 || filter.activityTypes.includes(entry.activityType)) && (filter.statuses === void 0 || filter.statuses.includes(entry.status)) && (filter.sources === void 0 || filter.sources.includes(entry.source)) && (filter.subjectAlias === void 0 || filter.subjectAlias === entry.subjectAlias),
|
|
1480
|
+
"INVALID_CONTRACT",
|
|
1481
|
+
"Admin Token activity result contains a row outside its metadata filters"
|
|
1482
|
+
);
|
|
1483
|
+
economyAssert(
|
|
1484
|
+
!rowAliases.has(entry.rowAlias),
|
|
1485
|
+
"DUPLICATE_IDENTIFIER",
|
|
1486
|
+
"Admin Token activity page cannot repeat a row alias"
|
|
1487
|
+
);
|
|
1488
|
+
rowAliases.add(entry.rowAlias);
|
|
1489
|
+
if (previous !== void 0) {
|
|
1490
|
+
economyAssert(
|
|
1491
|
+
compareActivityEntries(previous, entry, page.metadata.sort) < 0,
|
|
1492
|
+
"INVALID_CONTRACT",
|
|
1493
|
+
"Admin Token activity page does not use its declared stable sort"
|
|
1494
|
+
);
|
|
1495
|
+
}
|
|
1496
|
+
previous = entry;
|
|
1497
|
+
}
|
|
1498
|
+
}
|
|
1499
|
+
function assertAdminTokenActivityPageForRequest(page, request) {
|
|
1500
|
+
assertAdminTokenActivityPageRequest(request);
|
|
1501
|
+
assertAdminTokenActivityPage(page);
|
|
1502
|
+
economyAssert(
|
|
1503
|
+
page.metadata.fromInclusive === request.window.fromInclusive && page.metadata.toExclusive === request.window.toExclusive && page.metadata.sort === request.sort && sameActivityFilter(page.metadata.filter, request.filter) && page.metadata.pageLimit === request.limit && page.metadata.audience === request.audience && page.metadata.pseudonymVersion === request.pseudonymVersion,
|
|
1504
|
+
"INVALID_CONTRACT",
|
|
1505
|
+
"Admin Token activity result metadata does not match its normalized request"
|
|
1506
|
+
);
|
|
1507
|
+
}
|
|
1508
|
+
function assertAdminTokenTrendRequest(request) {
|
|
1509
|
+
assertExactKeys(
|
|
1510
|
+
request,
|
|
1511
|
+
["schemaVersion", "window", "granularity", "activityTypes"],
|
|
1512
|
+
"Admin Token trend request"
|
|
1513
|
+
);
|
|
1514
|
+
economyAssert(
|
|
1515
|
+
request.schemaVersion === ECONOMY_CONTRACT_VERSION && TREND_GRANULARITIES.has(request.granularity),
|
|
1516
|
+
"INVALID_CONTRACT",
|
|
1517
|
+
"Unsupported Admin Token trend request"
|
|
1518
|
+
);
|
|
1519
|
+
assertReportingWindow(
|
|
1520
|
+
request.window,
|
|
1521
|
+
request.granularity === "hour" ? ADMIN_TOKEN_MAXIMUM_HOURLY_WINDOW_DAYS : ADMIN_TOKEN_MAXIMUM_WINDOW_DAYS
|
|
1522
|
+
);
|
|
1523
|
+
if (request.activityTypes !== void 0) {
|
|
1524
|
+
assertUniqueValues(
|
|
1525
|
+
request.activityTypes,
|
|
1526
|
+
ACTIVITY_TYPES,
|
|
1527
|
+
"Admin Token trend activity types"
|
|
1528
|
+
);
|
|
1529
|
+
}
|
|
1530
|
+
}
|
|
1531
|
+
function medianHalfSubunits(values) {
|
|
1532
|
+
const ordered = [...values].sort(
|
|
1533
|
+
(left, right) => left === right ? 0 : left < right ? -1 : 1
|
|
1534
|
+
);
|
|
1535
|
+
const lower = ordered[Math.floor((ordered.length - 1) / 2)];
|
|
1536
|
+
const upper = ordered[Math.floor(ordered.length / 2)];
|
|
1537
|
+
economyAssert(
|
|
1538
|
+
lower !== void 0 && upper !== void 0,
|
|
1539
|
+
"INVALID_CONTRACT",
|
|
1540
|
+
"Median requires at least one value"
|
|
1541
|
+
);
|
|
1542
|
+
const sum = lower + upper;
|
|
1543
|
+
economyAssert(
|
|
1544
|
+
sum % 2n === 0n,
|
|
1545
|
+
"INVALID_AMOUNT",
|
|
1546
|
+
"Median cannot be represented in exact half TokenSubunits"
|
|
1547
|
+
);
|
|
1548
|
+
return sum / 2n;
|
|
1549
|
+
}
|
|
1550
|
+
function serializeExactStatistic(halfSubunits) {
|
|
1551
|
+
economyAssert(
|
|
1552
|
+
absolute(halfSubunits) <= MAXIMUM_STATISTIC_HALF_SUBUNITS,
|
|
1553
|
+
"AMOUNT_OUT_OF_RANGE",
|
|
1554
|
+
"Admin Token statistic exceeds its exact bounded representation"
|
|
1555
|
+
);
|
|
1556
|
+
if (halfSubunits % 2n === 0n) {
|
|
1557
|
+
return {
|
|
1558
|
+
numerator: (halfSubunits / 2n).toString(10),
|
|
1559
|
+
denominator: 1
|
|
1560
|
+
};
|
|
1561
|
+
}
|
|
1562
|
+
return {
|
|
1563
|
+
numerator: halfSubunits.toString(10),
|
|
1564
|
+
denominator: 2
|
|
1565
|
+
};
|
|
1566
|
+
}
|
|
1567
|
+
function parseExactStatistic(value, label) {
|
|
1568
|
+
assertExactKeys(value, ["numerator", "denominator"], label);
|
|
1569
|
+
economyAssert(
|
|
1570
|
+
typeof value.numerator === "string" && value.numerator.length <= 22 && EXACT_STATISTIC_INTEGER.test(value.numerator) && (value.denominator === 1 || value.denominator === 2),
|
|
1571
|
+
"INVALID_AMOUNT",
|
|
1572
|
+
`${label} must be an exact bounded rational TokenSubunit value`
|
|
1573
|
+
);
|
|
1574
|
+
const numerator = BigInt(value.numerator);
|
|
1575
|
+
economyAssert(
|
|
1576
|
+
value.denominator === 1 || numerator % 2n !== 0n,
|
|
1577
|
+
"INVALID_AMOUNT",
|
|
1578
|
+
`${label} must use a reduced exact representation`
|
|
1579
|
+
);
|
|
1580
|
+
const halfSubunits = numerator * BigInt(2 / value.denominator);
|
|
1581
|
+
economyAssert(
|
|
1582
|
+
absolute(halfSubunits) <= MAXIMUM_STATISTIC_HALF_SUBUNITS,
|
|
1583
|
+
"AMOUNT_OUT_OF_RANGE",
|
|
1584
|
+
`${label} exceeds its exact bounded representation`
|
|
1585
|
+
);
|
|
1586
|
+
return halfSubunits;
|
|
1587
|
+
}
|
|
1588
|
+
function classifyAnomaly(options) {
|
|
1589
|
+
if (options.absoluteDeltaHalfSubunits < options.minimumAbsoluteDeltaHalfSubunits) {
|
|
1590
|
+
return {
|
|
1591
|
+
status: "normal",
|
|
1592
|
+
explanationCode: "below-absolute-minimum"
|
|
1593
|
+
};
|
|
1594
|
+
}
|
|
1595
|
+
if (options.medianAbsoluteDeviationHalfSubunits === 0n) {
|
|
1596
|
+
return options.absoluteDeltaHalfSubunits > 0n ? {
|
|
1597
|
+
status: "irregular-spike",
|
|
1598
|
+
explanationCode: "zero-mad-absolute-threshold-exceeded"
|
|
1599
|
+
} : {
|
|
1600
|
+
status: "normal",
|
|
1601
|
+
explanationCode: "within-baseline-variation"
|
|
1602
|
+
};
|
|
1603
|
+
}
|
|
1604
|
+
const exceedsBaseline = options.absoluteDeltaHalfSubunits * 1000n >= options.medianAbsoluteDeviationHalfSubunits * BigInt(options.madMultiplierMilli);
|
|
1605
|
+
return exceedsBaseline ? {
|
|
1606
|
+
status: "irregular-spike",
|
|
1607
|
+
explanationCode: "median-mad-and-absolute-threshold-exceeded"
|
|
1608
|
+
} : {
|
|
1609
|
+
status: "normal",
|
|
1610
|
+
explanationCode: "within-baseline-variation"
|
|
1611
|
+
};
|
|
1612
|
+
}
|
|
1613
|
+
function createAdminTokenAnomalyIndicator(input) {
|
|
1614
|
+
assertExactKeys(
|
|
1615
|
+
input,
|
|
1616
|
+
[
|
|
1617
|
+
"observedAmount",
|
|
1618
|
+
"baselineSamples",
|
|
1619
|
+
"minimumAbsoluteDelta",
|
|
1620
|
+
"madMultiplierMilli"
|
|
1621
|
+
],
|
|
1622
|
+
"Admin Token anomaly input"
|
|
1623
|
+
);
|
|
1624
|
+
economyAssert(
|
|
1625
|
+
Array.isArray(input.baselineSamples) && input.baselineSamples.length === ADMIN_TOKEN_ANOMALY_BASELINE_DAYS && Number.isSafeInteger(input.madMultiplierMilli) && input.madMultiplierMilli >= 1 && input.madMultiplierMilli <= 1e6,
|
|
1626
|
+
"INVALID_CONTRACT",
|
|
1627
|
+
"Admin Token anomaly input requires 28 baselines and a bounded fixed-point multiplier"
|
|
1628
|
+
);
|
|
1629
|
+
const observed = parseTokenSubunits(input.observedAmount);
|
|
1630
|
+
const baseline = input.baselineSamples.map((sample) => {
|
|
1631
|
+
assertExactKeys(
|
|
1632
|
+
sample,
|
|
1633
|
+
["amount", "distinctSubjects"],
|
|
1634
|
+
"Admin Token anomaly baseline sample"
|
|
1635
|
+
);
|
|
1636
|
+
economyAssert(
|
|
1637
|
+
Number.isSafeInteger(sample.distinctSubjects) && sample.distinctSubjects >= ADMIN_TOKEN_MINIMUM_COHORT_SIZE,
|
|
1638
|
+
"INVALID_CONTRACT",
|
|
1639
|
+
"Admin Token anomaly baselines must exclude privacy-suppressed cohorts"
|
|
1640
|
+
);
|
|
1641
|
+
return parseTokenSubunits(sample.amount);
|
|
1642
|
+
});
|
|
1643
|
+
const minimum = parseTokenSubunits(input.minimumAbsoluteDelta);
|
|
1644
|
+
economyAssert(
|
|
1645
|
+
minimum > 0n,
|
|
1646
|
+
"INVALID_AMOUNT",
|
|
1647
|
+
"Admin Token anomaly absolute minimum must be positive"
|
|
1648
|
+
);
|
|
1649
|
+
const baselineHalfSubunits = baseline.map((amount) => amount * 2n);
|
|
1650
|
+
const medianHalf = medianHalfSubunits(baselineHalfSubunits);
|
|
1651
|
+
const medianAbsoluteDeviationHalf = medianHalfSubunits(
|
|
1652
|
+
baselineHalfSubunits.map((amount) => absolute(amount - medianHalf))
|
|
1653
|
+
);
|
|
1654
|
+
const deviationHalf = observed * 2n - medianHalf;
|
|
1655
|
+
const classification = classifyAnomaly({
|
|
1656
|
+
absoluteDeltaHalfSubunits: absolute(deviationHalf),
|
|
1657
|
+
medianAbsoluteDeviationHalfSubunits: medianAbsoluteDeviationHalf,
|
|
1658
|
+
minimumAbsoluteDeltaHalfSubunits: minimum * 2n,
|
|
1659
|
+
madMultiplierMilli: input.madMultiplierMilli
|
|
1660
|
+
});
|
|
1661
|
+
return {
|
|
1662
|
+
method: "same-window-median-mad-v1",
|
|
1663
|
+
...classification,
|
|
1664
|
+
baselineWindowCount: ADMIN_TOKEN_ANOMALY_BASELINE_DAYS,
|
|
1665
|
+
medianAmount: serializeExactStatistic(medianHalf),
|
|
1666
|
+
medianAbsoluteDeviation: serializeExactStatistic(medianAbsoluteDeviationHalf),
|
|
1667
|
+
minimumAbsoluteDelta: input.minimumAbsoluteDelta,
|
|
1668
|
+
deviationFromMedian: serializeExactStatistic(deviationHalf),
|
|
1669
|
+
madMultiplierMilli: input.madMultiplierMilli
|
|
1670
|
+
};
|
|
1671
|
+
}
|
|
1672
|
+
function createAdminTokenAnomalyUnavailable(input) {
|
|
1673
|
+
assertExactKeys(
|
|
1674
|
+
input,
|
|
1675
|
+
["reason", "eligibleBaselineWindowCount"],
|
|
1676
|
+
"Unavailable Admin Token anomaly input"
|
|
1677
|
+
);
|
|
1678
|
+
economyAssert(
|
|
1679
|
+
ANOMALY_UNAVAILABLE_REASONS.has(input.reason) && Number.isSafeInteger(input.eligibleBaselineWindowCount) && input.eligibleBaselineWindowCount >= 0 && input.eligibleBaselineWindowCount < ADMIN_TOKEN_ANOMALY_BASELINE_DAYS,
|
|
1680
|
+
"INVALID_CONTRACT",
|
|
1681
|
+
"Unavailable Admin Token anomaly requires a bounded reason and eligible baseline count"
|
|
1682
|
+
);
|
|
1683
|
+
return {
|
|
1684
|
+
method: "same-window-median-mad-v1",
|
|
1685
|
+
status: "unavailable",
|
|
1686
|
+
reason: input.reason,
|
|
1687
|
+
eligibleBaselineWindowCount: input.eligibleBaselineWindowCount,
|
|
1688
|
+
requiredBaselineWindowCount: ADMIN_TOKEN_ANOMALY_BASELINE_DAYS
|
|
1689
|
+
};
|
|
1690
|
+
}
|
|
1691
|
+
function assertAdminTokenAnomalyIndicator(anomaly, observedAmount) {
|
|
1692
|
+
assertExactKeys(
|
|
1693
|
+
anomaly,
|
|
1694
|
+
[
|
|
1695
|
+
"method",
|
|
1696
|
+
"status",
|
|
1697
|
+
"baselineWindowCount",
|
|
1698
|
+
"medianAmount",
|
|
1699
|
+
"medianAbsoluteDeviation",
|
|
1700
|
+
"minimumAbsoluteDelta",
|
|
1701
|
+
"deviationFromMedian",
|
|
1702
|
+
"madMultiplierMilli",
|
|
1703
|
+
"explanationCode"
|
|
1704
|
+
],
|
|
1705
|
+
"Admin Token anomaly indicator"
|
|
1706
|
+
);
|
|
1707
|
+
const observed = parseTokenSubunits(observedAmount);
|
|
1708
|
+
const medianHalf = parseExactStatistic(
|
|
1709
|
+
anomaly.medianAmount,
|
|
1710
|
+
"Admin Token anomaly median"
|
|
1711
|
+
);
|
|
1712
|
+
const madHalf = parseExactStatistic(
|
|
1713
|
+
anomaly.medianAbsoluteDeviation,
|
|
1714
|
+
"Admin Token anomaly median absolute deviation"
|
|
1715
|
+
);
|
|
1716
|
+
const minimum = parseTokenSubunits(anomaly.minimumAbsoluteDelta);
|
|
1717
|
+
const deviationHalf = parseExactStatistic(
|
|
1718
|
+
anomaly.deviationFromMedian,
|
|
1719
|
+
"Admin Token anomaly deviation"
|
|
1720
|
+
);
|
|
1721
|
+
economyAssert(
|
|
1722
|
+
anomaly.method === "same-window-median-mad-v1" && anomaly.baselineWindowCount === ADMIN_TOKEN_ANOMALY_BASELINE_DAYS && medianHalf >= TOKEN_SUBUNITS_MIN * 2n && medianHalf <= TOKEN_SUBUNITS_MAX * 2n && madHalf >= 0n && minimum > 0n && Number.isSafeInteger(anomaly.madMultiplierMilli) && anomaly.madMultiplierMilli >= 1 && anomaly.madMultiplierMilli <= 1e6 && deviationHalf === observed * 2n - medianHalf,
|
|
1723
|
+
"INVALID_CONTRACT",
|
|
1724
|
+
"Admin Token anomaly arithmetic or method is invalid"
|
|
1725
|
+
);
|
|
1726
|
+
const expected = classifyAnomaly({
|
|
1727
|
+
absoluteDeltaHalfSubunits: absolute(deviationHalf),
|
|
1728
|
+
medianAbsoluteDeviationHalfSubunits: madHalf,
|
|
1729
|
+
minimumAbsoluteDeltaHalfSubunits: minimum * 2n,
|
|
1730
|
+
madMultiplierMilli: anomaly.madMultiplierMilli
|
|
1731
|
+
});
|
|
1732
|
+
economyAssert(
|
|
1733
|
+
anomaly.status === expected.status && anomaly.explanationCode === expected.explanationCode,
|
|
1734
|
+
"INVALID_CONTRACT",
|
|
1735
|
+
"Admin Token anomaly classification is inconsistent with its explanation"
|
|
1736
|
+
);
|
|
1737
|
+
}
|
|
1738
|
+
function assertAdminTokenAnomalyUnavailable(anomaly) {
|
|
1739
|
+
assertExactKeys(
|
|
1740
|
+
anomaly,
|
|
1741
|
+
[
|
|
1742
|
+
"method",
|
|
1743
|
+
"status",
|
|
1744
|
+
"reason",
|
|
1745
|
+
"eligibleBaselineWindowCount",
|
|
1746
|
+
"requiredBaselineWindowCount"
|
|
1747
|
+
],
|
|
1748
|
+
"Unavailable Admin Token anomaly"
|
|
1749
|
+
);
|
|
1750
|
+
economyAssert(
|
|
1751
|
+
anomaly.method === "same-window-median-mad-v1" && anomaly.status === "unavailable" && ANOMALY_UNAVAILABLE_REASONS.has(anomaly.reason) && Number.isSafeInteger(anomaly.eligibleBaselineWindowCount) && anomaly.eligibleBaselineWindowCount >= 0 && anomaly.eligibleBaselineWindowCount < ADMIN_TOKEN_ANOMALY_BASELINE_DAYS && anomaly.requiredBaselineWindowCount === ADMIN_TOKEN_ANOMALY_BASELINE_DAYS,
|
|
1752
|
+
"INVALID_CONTRACT",
|
|
1753
|
+
"Unavailable Admin Token anomaly metadata is invalid"
|
|
1754
|
+
);
|
|
1755
|
+
}
|
|
1756
|
+
function assertTrendBucketAlignment(start, end, granularity) {
|
|
1757
|
+
const expectedDuration = granularity === "hour" ? HOUR_MILLISECONDS : DAY_MILLISECONDS;
|
|
1758
|
+
const date = new Date(start);
|
|
1759
|
+
const aligned = date.getUTCMinutes() === 0 && date.getUTCSeconds() === 0 && date.getUTCMilliseconds() === 0 && (granularity === "hour" || date.getUTCHours() === 0);
|
|
1760
|
+
economyAssert(
|
|
1761
|
+
aligned && end - start === expectedDuration,
|
|
1762
|
+
"INVALID_TIME_WINDOW",
|
|
1763
|
+
"Admin Token trend bucket is not aligned to its declared granularity"
|
|
1764
|
+
);
|
|
1765
|
+
}
|
|
1766
|
+
function assertTrendAggregate(aggregate) {
|
|
1767
|
+
assertPlainObject(aggregate, "Admin Token trend aggregate");
|
|
1768
|
+
if (aggregate.visibility === "suppressed") {
|
|
1769
|
+
assertExactKeys(
|
|
1770
|
+
aggregate,
|
|
1771
|
+
["visibility", "reason", "threshold"],
|
|
1772
|
+
"Suppressed Admin Token trend aggregate"
|
|
1773
|
+
);
|
|
1774
|
+
economyAssert(
|
|
1775
|
+
aggregate.reason === "cohort-below-minimum" && aggregate.threshold === ADMIN_TOKEN_MINIMUM_COHORT_SIZE,
|
|
1776
|
+
"INVALID_CONTRACT",
|
|
1777
|
+
"Suppressed Admin Token trend aggregate has invalid privacy metadata"
|
|
1778
|
+
);
|
|
1779
|
+
return;
|
|
1780
|
+
}
|
|
1781
|
+
assertExactKeys(
|
|
1782
|
+
aggregate,
|
|
1783
|
+
[
|
|
1784
|
+
"visibility",
|
|
1785
|
+
"distinctSubjects",
|
|
1786
|
+
"activityCount",
|
|
1787
|
+
"signedAmount"
|
|
1788
|
+
],
|
|
1789
|
+
"Reported Admin Token trend aggregate"
|
|
1790
|
+
);
|
|
1791
|
+
parseTokenSubunits(aggregate.signedAmount);
|
|
1792
|
+
economyAssert(
|
|
1793
|
+
aggregate.visibility === "reported" && Number.isSafeInteger(aggregate.distinctSubjects) && aggregate.distinctSubjects >= ADMIN_TOKEN_MINIMUM_COHORT_SIZE && Number.isSafeInteger(aggregate.activityCount) && aggregate.activityCount >= aggregate.distinctSubjects,
|
|
1794
|
+
"INVALID_CONTRACT",
|
|
1795
|
+
"Reported Admin Token trend aggregate is invalid or below the privacy threshold"
|
|
1796
|
+
);
|
|
1797
|
+
}
|
|
1798
|
+
function assertAdminTokenTrendResult(result) {
|
|
1799
|
+
assertExactKeys(
|
|
1800
|
+
result,
|
|
1801
|
+
["schemaVersion", "series", "metadata"],
|
|
1802
|
+
"Admin Token trend result"
|
|
1803
|
+
);
|
|
1804
|
+
assertExactKeys(
|
|
1805
|
+
result.metadata,
|
|
1806
|
+
[
|
|
1807
|
+
"schemaVersion",
|
|
1808
|
+
"generatedAt",
|
|
1809
|
+
"fromInclusive",
|
|
1810
|
+
"toExclusive",
|
|
1811
|
+
"granularity",
|
|
1812
|
+
"activityTypes",
|
|
1813
|
+
"minimumCohortSize",
|
|
1814
|
+
"anomalyBaselineDays",
|
|
1815
|
+
"rawIdentifiersIncluded"
|
|
1816
|
+
],
|
|
1817
|
+
"Admin Token trend metadata"
|
|
1818
|
+
);
|
|
1819
|
+
economyAssert(
|
|
1820
|
+
result.schemaVersion === ECONOMY_CONTRACT_VERSION && result.metadata.schemaVersion === ECONOMY_CONTRACT_VERSION && TREND_GRANULARITIES.has(result.metadata.granularity) && result.metadata.minimumCohortSize === ADMIN_TOKEN_MINIMUM_COHORT_SIZE && result.metadata.anomalyBaselineDays === ADMIN_TOKEN_ANOMALY_BASELINE_DAYS && result.metadata.rawIdentifiersIncluded === false && Array.isArray(result.series) && result.series.length <= ADMIN_TOKEN_MAXIMUM_TREND_POINTS,
|
|
1821
|
+
"INVALID_CONTRACT",
|
|
1822
|
+
"Unsupported or unbounded Admin Token trend result"
|
|
1823
|
+
);
|
|
1824
|
+
assertUniqueValues(
|
|
1825
|
+
result.metadata.activityTypes,
|
|
1826
|
+
ACTIVITY_TYPES,
|
|
1827
|
+
"Admin Token trend result activity types"
|
|
1828
|
+
);
|
|
1829
|
+
const window = assertReportingWindow(
|
|
1830
|
+
{
|
|
1831
|
+
fromInclusive: result.metadata.fromInclusive,
|
|
1832
|
+
toExclusive: result.metadata.toExclusive
|
|
1833
|
+
},
|
|
1834
|
+
result.metadata.granularity === "hour" ? ADMIN_TOKEN_MAXIMUM_HOURLY_WINDOW_DAYS : ADMIN_TOKEN_MAXIMUM_WINDOW_DAYS
|
|
1835
|
+
);
|
|
1836
|
+
parseIsoTimestamp(result.metadata.generatedAt);
|
|
1837
|
+
const pointKeys = /* @__PURE__ */ new Set();
|
|
1838
|
+
let previousKey;
|
|
1839
|
+
for (const point of result.series) {
|
|
1840
|
+
assertExactKeys(
|
|
1841
|
+
point,
|
|
1842
|
+
[
|
|
1843
|
+
"schemaVersion",
|
|
1844
|
+
"bucketStart",
|
|
1845
|
+
"bucketEnd",
|
|
1846
|
+
"activityType",
|
|
1847
|
+
"aggregate",
|
|
1848
|
+
"anomaly"
|
|
1849
|
+
],
|
|
1850
|
+
"Admin Token trend point"
|
|
1851
|
+
);
|
|
1852
|
+
economyAssert(
|
|
1853
|
+
point.schemaVersion === ECONOMY_CONTRACT_VERSION && ACTIVITY_TYPES.has(point.activityType) && result.metadata.activityTypes.includes(point.activityType),
|
|
1854
|
+
"INVALID_CONTRACT",
|
|
1855
|
+
"Unsupported Admin Token trend point"
|
|
1856
|
+
);
|
|
1857
|
+
const start = parseIsoTimestamp(point.bucketStart);
|
|
1858
|
+
const end = parseIsoTimestamp(point.bucketEnd);
|
|
1859
|
+
economyAssert(
|
|
1860
|
+
start >= window.from && end <= window.to,
|
|
1861
|
+
"INVALID_TIME_WINDOW",
|
|
1862
|
+
"Admin Token trend bucket falls outside the declared result window"
|
|
1863
|
+
);
|
|
1864
|
+
assertTrendBucketAlignment(start, end, result.metadata.granularity);
|
|
1865
|
+
assertTrendAggregate(point.aggregate);
|
|
1866
|
+
if (point.aggregate.visibility === "suppressed") {
|
|
1867
|
+
economyAssert(
|
|
1868
|
+
point.anomaly === void 0,
|
|
1869
|
+
"INVALID_CONTRACT",
|
|
1870
|
+
"Suppressed Admin Token cohorts cannot include anomaly details"
|
|
1871
|
+
);
|
|
1872
|
+
} else {
|
|
1873
|
+
economyAssert(
|
|
1874
|
+
point.anomaly !== void 0,
|
|
1875
|
+
"INVALID_CONTRACT",
|
|
1876
|
+
"Reported Admin Token cohorts require an anomaly result"
|
|
1877
|
+
);
|
|
1878
|
+
if (point.anomaly.status === "unavailable") {
|
|
1879
|
+
assertAdminTokenAnomalyUnavailable(point.anomaly);
|
|
1880
|
+
} else {
|
|
1881
|
+
assertAdminTokenAnomalyIndicator(
|
|
1882
|
+
point.anomaly,
|
|
1883
|
+
point.aggregate.signedAmount
|
|
1884
|
+
);
|
|
1885
|
+
}
|
|
1886
|
+
}
|
|
1887
|
+
const key = `${point.bucketStart}\0${point.activityType}`;
|
|
1888
|
+
economyAssert(
|
|
1889
|
+
!pointKeys.has(key) && (previousKey === void 0 || previousKey < key),
|
|
1890
|
+
"DUPLICATE_IDENTIFIER",
|
|
1891
|
+
"Admin Token trend points must be unique and stably ordered"
|
|
1892
|
+
);
|
|
1893
|
+
pointKeys.add(key);
|
|
1894
|
+
previousKey = key;
|
|
1895
|
+
}
|
|
1896
|
+
}
|
|
1897
|
+
function assertAdminTokenTrendResultForRequest(result, request) {
|
|
1898
|
+
assertAdminTokenTrendRequest(request);
|
|
1899
|
+
assertAdminTokenTrendResult(result);
|
|
1900
|
+
const requestedActivityTypes = request.activityTypes ?? [...ACTIVITY_TYPES];
|
|
1901
|
+
economyAssert(
|
|
1902
|
+
result.metadata.fromInclusive === request.window.fromInclusive && result.metadata.toExclusive === request.window.toExclusive && result.metadata.granularity === request.granularity && sameOptionalValues(
|
|
1903
|
+
result.metadata.activityTypes,
|
|
1904
|
+
requestedActivityTypes
|
|
1905
|
+
),
|
|
1906
|
+
"INVALID_CONTRACT",
|
|
1907
|
+
"Admin Token trend result metadata does not match its normalized request"
|
|
1908
|
+
);
|
|
1909
|
+
}
|
|
1910
|
+
|
|
739
1911
|
// src/allocations.ts
|
|
740
1912
|
function assertWholePositive(amount, label) {
|
|
741
1913
|
const parsed = parseTokenSubunits(amount);
|
|
@@ -1072,7 +2244,7 @@ var COMMAND_ENVELOPE_KEYS = /* @__PURE__ */ new Set([
|
|
|
1072
2244
|
"acceptedRegion",
|
|
1073
2245
|
"writerFencingToken"
|
|
1074
2246
|
]);
|
|
1075
|
-
function
|
|
2247
|
+
function assertExactKeys2(value, allowedKeys, label) {
|
|
1076
2248
|
economyAssert(
|
|
1077
2249
|
value !== null && typeof value === "object" && !Array.isArray(value),
|
|
1078
2250
|
"INVALID_CONTRACT",
|
|
@@ -1116,7 +2288,7 @@ function assertRelationshipContext(relationshipId, authorizationVersion) {
|
|
|
1116
2288
|
);
|
|
1117
2289
|
}
|
|
1118
2290
|
function assertEconomyHmacFingerprint(fingerprint, expectedDomain) {
|
|
1119
|
-
|
|
2291
|
+
assertExactKeys2(
|
|
1120
2292
|
fingerprint,
|
|
1121
2293
|
/* @__PURE__ */ new Set([
|
|
1122
2294
|
"schemaVersion",
|
|
@@ -1141,7 +2313,7 @@ function assertEconomyHmacFingerprint(fingerprint, expectedDomain) {
|
|
|
1141
2313
|
);
|
|
1142
2314
|
}
|
|
1143
2315
|
function assertEconomyAuthorizationEvidence(evidence) {
|
|
1144
|
-
|
|
2316
|
+
assertExactKeys2(
|
|
1145
2317
|
evidence,
|
|
1146
2318
|
/* @__PURE__ */ new Set([
|
|
1147
2319
|
"schemaVersion",
|
|
@@ -1178,7 +2350,7 @@ function assertEconomyAuthorizationEvidence(evidence) {
|
|
|
1178
2350
|
);
|
|
1179
2351
|
}
|
|
1180
2352
|
function assertCausationReference(causation) {
|
|
1181
|
-
|
|
2353
|
+
assertExactKeys2(
|
|
1182
2354
|
causation,
|
|
1183
2355
|
/* @__PURE__ */ new Set(["schemaVersion", "kind", "causationId"]),
|
|
1184
2356
|
"Economy causation reference"
|
|
@@ -1233,7 +2405,7 @@ function assertCommandSourcePrincipal(envelope) {
|
|
|
1233
2405
|
}
|
|
1234
2406
|
}
|
|
1235
2407
|
function assertAuditedEconomyCommandEnvelope(envelope) {
|
|
1236
|
-
|
|
2408
|
+
assertExactKeys2(
|
|
1237
2409
|
envelope,
|
|
1238
2410
|
COMMAND_ENVELOPE_KEYS,
|
|
1239
2411
|
"Audited economy command envelope"
|
|
@@ -1299,7 +2471,7 @@ function assertAuditedEconomyCommandEnvelope(envelope) {
|
|
|
1299
2471
|
);
|
|
1300
2472
|
}
|
|
1301
2473
|
function assertEconomyProviderEvidenceHash(evidence) {
|
|
1302
|
-
|
|
2474
|
+
assertExactKeys2(
|
|
1303
2475
|
evidence,
|
|
1304
2476
|
/* @__PURE__ */ new Set([
|
|
1305
2477
|
"schemaVersion",
|
|
@@ -1370,7 +2542,7 @@ function assertEconomyProviderEvidenceHash(evidence) {
|
|
|
1370
2542
|
}
|
|
1371
2543
|
}
|
|
1372
2544
|
function assertEconomyEncryptedOperationalHandleBinding(binding) {
|
|
1373
|
-
|
|
2545
|
+
assertExactKeys2(
|
|
1374
2546
|
binding,
|
|
1375
2547
|
/* @__PURE__ */ new Set([
|
|
1376
2548
|
"schemaVersion",
|
|
@@ -1405,7 +2577,7 @@ function assertEconomyEncryptedOperationalHandleBinding(binding) {
|
|
|
1405
2577
|
parseIsoTimestamp(binding.createdAt);
|
|
1406
2578
|
}
|
|
1407
2579
|
function assertEvidenceRecordReference(reference) {
|
|
1408
|
-
|
|
2580
|
+
assertExactKeys2(
|
|
1409
2581
|
reference,
|
|
1410
2582
|
/* @__PURE__ */ new Set(["schemaVersion", "recordId", "contentHash"]),
|
|
1411
2583
|
"Evidence record reference"
|
|
@@ -1436,7 +2608,7 @@ function assertUniqueSortedReferences(references, label) {
|
|
|
1436
2608
|
}
|
|
1437
2609
|
}
|
|
1438
2610
|
function assertEconomyProviderEvidenceManifest(manifest) {
|
|
1439
|
-
|
|
2611
|
+
assertExactKeys2(
|
|
1440
2612
|
manifest,
|
|
1441
2613
|
/* @__PURE__ */ new Set([
|
|
1442
2614
|
"schemaVersion",
|
|
@@ -1478,7 +2650,7 @@ function assertEconomyProviderEvidenceManifest(manifest) {
|
|
|
1478
2650
|
parseIsoTimestamp(manifest.createdAt);
|
|
1479
2651
|
}
|
|
1480
2652
|
function assertEconomyAcceptedCommandReceipt(receipt) {
|
|
1481
|
-
|
|
2653
|
+
assertExactKeys2(
|
|
1482
2654
|
receipt,
|
|
1483
2655
|
/* @__PURE__ */ new Set([
|
|
1484
2656
|
"schemaVersion",
|
|
@@ -1502,7 +2674,7 @@ function assertEconomyAcceptedCommandReceipt(receipt) {
|
|
|
1502
2674
|
parseIsoTimestamp(receipt.acceptedAt);
|
|
1503
2675
|
}
|
|
1504
2676
|
function assertEconomyCommandResultReceipt(receipt) {
|
|
1505
|
-
|
|
2677
|
+
assertExactKeys2(
|
|
1506
2678
|
receipt,
|
|
1507
2679
|
/* @__PURE__ */ new Set([
|
|
1508
2680
|
"schemaVersion",
|
|
@@ -1559,7 +2731,7 @@ function assertEconomyCommandResultReceipt(receipt) {
|
|
|
1559
2731
|
}
|
|
1560
2732
|
}
|
|
1561
2733
|
function assertEconomyAuditedIdempotencyScope(scope) {
|
|
1562
|
-
|
|
2734
|
+
assertExactKeys2(
|
|
1563
2735
|
scope,
|
|
1564
2736
|
/* @__PURE__ */ new Set([
|
|
1565
2737
|
"schemaVersion",
|
|
@@ -1590,7 +2762,7 @@ function assertEconomyAuditedIdempotencyScope(scope) {
|
|
|
1590
2762
|
);
|
|
1591
2763
|
}
|
|
1592
2764
|
function assertEconomyAuditedIdempotencyResult(result) {
|
|
1593
|
-
|
|
2765
|
+
assertExactKeys2(
|
|
1594
2766
|
result,
|
|
1595
2767
|
/* @__PURE__ */ new Set([
|
|
1596
2768
|
"schemaVersion",
|
|
@@ -1881,7 +3053,7 @@ var MANIFEST_KEYS = /* @__PURE__ */ new Set([
|
|
|
1881
3053
|
"recordReferences",
|
|
1882
3054
|
"committedAt"
|
|
1883
3055
|
]);
|
|
1884
|
-
function
|
|
3056
|
+
function assertExactKeys3(value, allowedKeys, label) {
|
|
1885
3057
|
economyAssert(
|
|
1886
3058
|
value !== null && typeof value === "object" && !Array.isArray(value),
|
|
1887
3059
|
"INVALID_CONTRACT",
|
|
@@ -1919,7 +3091,7 @@ function referenceOrder(left, right) {
|
|
|
1919
3091
|
return byKind === 0 ? compareUnicodeCodeUnits(left.recordId, right.recordId) : byKind;
|
|
1920
3092
|
}
|
|
1921
3093
|
function assertEconomyAuthorityRecordReference(reference) {
|
|
1922
|
-
|
|
3094
|
+
assertExactKeys3(
|
|
1923
3095
|
reference,
|
|
1924
3096
|
/* @__PURE__ */ new Set([
|
|
1925
3097
|
"schemaVersion",
|
|
@@ -2083,7 +3255,7 @@ function assertCommitAllowedInState(manifest) {
|
|
|
2083
3255
|
}
|
|
2084
3256
|
}
|
|
2085
3257
|
function assertEconomyAuthorityCommitManifest(manifest) {
|
|
2086
|
-
|
|
3258
|
+
assertExactKeys3(manifest, MANIFEST_KEYS, "Authority commit manifest");
|
|
2087
3259
|
economyAssert(
|
|
2088
3260
|
manifest.schemaVersion === ECONOMY_CONTRACT_VERSION && COMMIT_KINDS.has(manifest.commitKind) && AUTHORITY_STATES.has(manifest.authorityStateBefore) && AUTHORITY_STATES.has(manifest.authorityStateAfter),
|
|
2089
3261
|
"INVALID_CONTRACT",
|
|
@@ -2130,7 +3302,7 @@ function assertEconomyAuthorityCommitManifest(manifest) {
|
|
|
2130
3302
|
parseIsoTimestamp(manifest.committedAt);
|
|
2131
3303
|
}
|
|
2132
3304
|
function assertEconomyAuthorityHead(head) {
|
|
2133
|
-
|
|
3305
|
+
assertExactKeys3(head, HEAD_KEYS, "Economy authority head");
|
|
2134
3306
|
economyAssert(
|
|
2135
3307
|
head.schemaVersion === ECONOMY_CONTRACT_VERSION && AUTHORITY_STATES.has(head.state),
|
|
2136
3308
|
"INVALID_CONTRACT",
|
|
@@ -2189,7 +3361,7 @@ function advanceEconomyAuthorityHead(head, manifest, manifestCanonicalHash) {
|
|
|
2189
3361
|
};
|
|
2190
3362
|
}
|
|
2191
3363
|
function assertEconomyIntegrityVerificationReceipt(receipt) {
|
|
2192
|
-
|
|
3364
|
+
assertExactKeys3(
|
|
2193
3365
|
receipt,
|
|
2194
3366
|
/* @__PURE__ */ new Set([
|
|
2195
3367
|
"schemaVersion",
|
|
@@ -2335,7 +3507,7 @@ function assertEconomyIntegrityVerificationReceipt(receipt) {
|
|
|
2335
3507
|
parseIsoTimestamp(receipt.verifiedAt);
|
|
2336
3508
|
}
|
|
2337
3509
|
function assertEconomyIntegrityAnchorManifest(manifest) {
|
|
2338
|
-
|
|
3510
|
+
assertExactKeys3(
|
|
2339
3511
|
manifest,
|
|
2340
3512
|
/* @__PURE__ */ new Set([
|
|
2341
3513
|
"schemaVersion",
|
|
@@ -2497,7 +3669,7 @@ function sortEconomyAuthorityRecordReferences(references) {
|
|
|
2497
3669
|
}
|
|
2498
3670
|
|
|
2499
3671
|
// src/ledger.ts
|
|
2500
|
-
var
|
|
3672
|
+
var ACTIVITY_TYPES2 = /* @__PURE__ */ new Set([
|
|
2501
3673
|
"purchase",
|
|
2502
3674
|
"subscription",
|
|
2503
3675
|
"rewarded-ad",
|
|
@@ -2514,14 +3686,14 @@ var ACTIVITY_TYPES = /* @__PURE__ */ new Set([
|
|
|
2514
3686
|
"event",
|
|
2515
3687
|
"competition"
|
|
2516
3688
|
]);
|
|
2517
|
-
var
|
|
3689
|
+
var ACTIVITY_STATUSES2 = /* @__PURE__ */ new Set([
|
|
2518
3690
|
"pending",
|
|
2519
3691
|
"held",
|
|
2520
3692
|
"settled",
|
|
2521
3693
|
"reversed",
|
|
2522
3694
|
"failed"
|
|
2523
3695
|
]);
|
|
2524
|
-
var
|
|
3696
|
+
var ACTIVITY_SOURCES2 = /* @__PURE__ */ new Set([
|
|
2525
3697
|
"shopify",
|
|
2526
3698
|
"ayet",
|
|
2527
3699
|
"bitlabs",
|
|
@@ -2551,7 +3723,7 @@ function assertActivityEntry(entry) {
|
|
|
2551
3723
|
);
|
|
2552
3724
|
assertEconomyIdentifier(entry.transactionId, "transactionId");
|
|
2553
3725
|
economyAssert(
|
|
2554
|
-
|
|
3726
|
+
ACTIVITY_TYPES2.has(entry.activityType) && ACTIVITY_STATUSES2.has(entry.status) && ACTIVITY_SOURCES2.has(entry.source),
|
|
2555
3727
|
"INVALID_CONTRACT",
|
|
2556
3728
|
"Activity type, status, or source is unsupported"
|
|
2557
3729
|
);
|
|
@@ -2589,7 +3761,7 @@ function assertBalancedTransaction(transaction) {
|
|
|
2589
3761
|
assertEconomyIdentifier(transaction.transactionId, "transactionId");
|
|
2590
3762
|
assertEconomyIdentifier(transaction.idempotencyKey, "idempotencyKey");
|
|
2591
3763
|
economyAssert(
|
|
2592
|
-
|
|
3764
|
+
ACTIVITY_TYPES2.has(transaction.activityType) && ACTIVITY_STATUSES2.has(transaction.status),
|
|
2593
3765
|
"INVALID_CONTRACT",
|
|
2594
3766
|
"Transaction activity type or status is unsupported"
|
|
2595
3767
|
);
|
|
@@ -4628,7 +5800,7 @@ var DECISIONS = /* @__PURE__ */ new Set([
|
|
|
4628
5800
|
"approve",
|
|
4629
5801
|
"reject"
|
|
4630
5802
|
]);
|
|
4631
|
-
function
|
|
5803
|
+
function assertExactKeys4(value, allowed, label) {
|
|
4632
5804
|
economyAssert(
|
|
4633
5805
|
value !== null && typeof value === "object" && !Array.isArray(value),
|
|
4634
5806
|
"INVALID_CONTRACT",
|
|
@@ -4655,7 +5827,7 @@ function assertReasonCode(reasonCode) {
|
|
|
4655
5827
|
);
|
|
4656
5828
|
}
|
|
4657
5829
|
function assertOperatorAdjustmentPreview(preview) {
|
|
4658
|
-
|
|
5830
|
+
assertExactKeys4(preview, PREVIEW_KEYS, "Operator adjustment preview");
|
|
4659
5831
|
economyAssert(
|
|
4660
5832
|
preview.schemaVersion === ECONOMY_CONTRACT_VERSION && OPERATIONS.has(preview.operation) && TARGET_COMPONENTS.has(preview.targetComponent) && TRANSFER_POLICIES.has(preview.transferPolicy) && preview.refundPolicy === "not-refundable",
|
|
4661
5833
|
"INVALID_CONTRACT",
|
|
@@ -4734,7 +5906,7 @@ function canonicalOperatorAdjustmentPreviewPayload(preview) {
|
|
|
4734
5906
|
function assertOperatorAdjustmentProposal(proposal, preview, expectedPreviewHash) {
|
|
4735
5907
|
assertOperatorAdjustmentPreview(preview);
|
|
4736
5908
|
assertCanonicalHash6(expectedPreviewHash, "expectedPreviewHash");
|
|
4737
|
-
|
|
5909
|
+
assertExactKeys4(proposal, PROPOSAL_KEYS, "Operator adjustment proposal");
|
|
4738
5910
|
economyAssert(
|
|
4739
5911
|
proposal.schemaVersion === ECONOMY_CONTRACT_VERSION && proposal.status === "pending-approval",
|
|
4740
5912
|
"INVALID_CONTRACT",
|
|
@@ -4761,7 +5933,7 @@ function assertOperatorAdjustmentProposal(proposal, preview, expectedPreviewHash
|
|
|
4761
5933
|
);
|
|
4762
5934
|
}
|
|
4763
5935
|
function canonicalOperatorAdjustmentProposalPayload(proposal) {
|
|
4764
|
-
|
|
5936
|
+
assertExactKeys4(proposal, PROPOSAL_KEYS, "Operator adjustment proposal");
|
|
4765
5937
|
return JSON.stringify({
|
|
4766
5938
|
schemaVersion: proposal.schemaVersion,
|
|
4767
5939
|
proposalId: proposal.proposalId,
|
|
@@ -4776,7 +5948,7 @@ function canonicalOperatorAdjustmentProposalPayload(proposal) {
|
|
|
4776
5948
|
function assertOperatorAdjustmentDecision(decision, proposal, preview, expectedPreviewHash, expectedProposalHash) {
|
|
4777
5949
|
assertOperatorAdjustmentProposal(proposal, preview, expectedPreviewHash);
|
|
4778
5950
|
assertCanonicalHash6(expectedProposalHash, "expectedProposalHash");
|
|
4779
|
-
|
|
5951
|
+
assertExactKeys4(decision, DECISION_KEYS, "Operator adjustment decision");
|
|
4780
5952
|
economyAssert(
|
|
4781
5953
|
decision.schemaVersion === ECONOMY_CONTRACT_VERSION && DECISIONS.has(decision.decision),
|
|
4782
5954
|
"INVALID_CONTRACT",
|
|
@@ -4819,7 +5991,7 @@ function assertOperatorAdjustmentDecision(decision, proposal, preview, expectedP
|
|
|
4819
5991
|
);
|
|
4820
5992
|
}
|
|
4821
5993
|
function canonicalOperatorAdjustmentDecisionPayload(decision) {
|
|
4822
|
-
|
|
5994
|
+
assertExactKeys4(decision, DECISION_KEYS, "Operator adjustment decision");
|
|
4823
5995
|
return JSON.stringify({
|
|
4824
5996
|
schemaVersion: decision.schemaVersion,
|
|
4825
5997
|
decisionId: decision.decisionId,
|
|
@@ -4843,7 +6015,7 @@ function assertOperatorAdjustmentExecution(execution, preview, proposal, decisio
|
|
|
4843
6015
|
expectedProposalHash
|
|
4844
6016
|
);
|
|
4845
6017
|
assertCanonicalHash6(expectedDecisionHash, "expectedDecisionHash");
|
|
4846
|
-
|
|
6018
|
+
assertExactKeys4(execution, EXECUTION_KEYS, "Operator adjustment execution");
|
|
4847
6019
|
economyAssert(
|
|
4848
6020
|
execution.schemaVersion === ECONOMY_CONTRACT_VERSION,
|
|
4849
6021
|
"INVALID_CONTRACT",
|
|
@@ -4874,7 +6046,7 @@ function assertOperatorAdjustmentExecution(execution, preview, proposal, decisio
|
|
|
4874
6046
|
);
|
|
4875
6047
|
}
|
|
4876
6048
|
function canonicalOperatorAdjustmentExecutionPayload(execution) {
|
|
4877
|
-
|
|
6049
|
+
assertExactKeys4(execution, EXECUTION_KEYS, "Operator adjustment execution");
|
|
4878
6050
|
return JSON.stringify({
|
|
4879
6051
|
schemaVersion: execution.schemaVersion,
|
|
4880
6052
|
executionId: execution.executionId,
|
|
@@ -5919,7 +7091,7 @@ function createProjectionSnapshot(transactions, rebuiltAt) {
|
|
|
5919
7091
|
}
|
|
5920
7092
|
|
|
5921
7093
|
// src/ports/query.ts
|
|
5922
|
-
var
|
|
7094
|
+
var ACTIVITY_TYPES3 = /* @__PURE__ */ new Set([
|
|
5923
7095
|
"purchase",
|
|
5924
7096
|
"subscription",
|
|
5925
7097
|
"rewarded-ad",
|
|
@@ -5936,14 +7108,14 @@ var ACTIVITY_TYPES2 = /* @__PURE__ */ new Set([
|
|
|
5936
7108
|
"event",
|
|
5937
7109
|
"competition"
|
|
5938
7110
|
]);
|
|
5939
|
-
var
|
|
7111
|
+
var ACTIVITY_STATUSES3 = /* @__PURE__ */ new Set([
|
|
5940
7112
|
"pending",
|
|
5941
7113
|
"held",
|
|
5942
7114
|
"settled",
|
|
5943
7115
|
"reversed",
|
|
5944
7116
|
"failed"
|
|
5945
7117
|
]);
|
|
5946
|
-
var
|
|
7118
|
+
var ACTIVITY_SOURCES3 = /* @__PURE__ */ new Set([
|
|
5947
7119
|
"shopify",
|
|
5948
7120
|
"ayet",
|
|
5949
7121
|
"bitlabs",
|
|
@@ -5971,14 +7143,14 @@ function assertSafeDisplayString(value, label) {
|
|
|
5971
7143
|
`${label} must be bounded and safe for display`
|
|
5972
7144
|
);
|
|
5973
7145
|
}
|
|
5974
|
-
function
|
|
7146
|
+
function assertOpaqueCursor2(value) {
|
|
5975
7147
|
economyAssert(
|
|
5976
7148
|
typeof value === "string" && value.length > 0 && value.length <= 512 && !hasControlCharacters2(value),
|
|
5977
7149
|
"INVALID_CONTRACT",
|
|
5978
7150
|
"Activity cursor must be a bounded opaque value"
|
|
5979
7151
|
);
|
|
5980
7152
|
}
|
|
5981
|
-
function
|
|
7153
|
+
function assertUniqueValues2(values, allowed, label) {
|
|
5982
7154
|
const unique = new Set(values);
|
|
5983
7155
|
economyAssert(
|
|
5984
7156
|
values.length > 0 && values.length === unique.size && values.every((value) => allowed.has(value)),
|
|
@@ -6241,7 +7413,7 @@ function assertWalletActivityEntry(entry) {
|
|
|
6241
7413
|
assertEconomyIdentifier(entry.activityId, "activityId");
|
|
6242
7414
|
assertEconomyIdentifier(entry.walletId, "walletId");
|
|
6243
7415
|
economyAssert(
|
|
6244
|
-
|
|
7416
|
+
ACTIVITY_TYPES3.has(entry.activityType) && ACTIVITY_STATUSES3.has(entry.status) && ACTIVITY_SOURCES3.has(entry.source),
|
|
6245
7417
|
"INVALID_CONTRACT",
|
|
6246
7418
|
"Wallet activity type, status, or source is unsupported"
|
|
6247
7419
|
);
|
|
@@ -6289,20 +7461,20 @@ function assertWalletActivityPageRequest(request) {
|
|
|
6289
7461
|
"Activity page limit must be between one and 100"
|
|
6290
7462
|
);
|
|
6291
7463
|
if (request.cursor !== void 0) {
|
|
6292
|
-
|
|
7464
|
+
assertOpaqueCursor2(request.cursor);
|
|
6293
7465
|
}
|
|
6294
7466
|
const filter = request.filter;
|
|
6295
7467
|
if (filter === void 0) {
|
|
6296
7468
|
return;
|
|
6297
7469
|
}
|
|
6298
7470
|
if (filter.activityTypes !== void 0) {
|
|
6299
|
-
|
|
7471
|
+
assertUniqueValues2(filter.activityTypes, ACTIVITY_TYPES3, "Activity types");
|
|
6300
7472
|
}
|
|
6301
7473
|
if (filter.statuses !== void 0) {
|
|
6302
|
-
|
|
7474
|
+
assertUniqueValues2(filter.statuses, ACTIVITY_STATUSES3, "Activity statuses");
|
|
6303
7475
|
}
|
|
6304
7476
|
if (filter.sources !== void 0) {
|
|
6305
|
-
|
|
7477
|
+
assertUniqueValues2(filter.sources, ACTIVITY_SOURCES3, "Activity sources");
|
|
6306
7478
|
}
|
|
6307
7479
|
if (filter.beneficiaryAccountId !== void 0) {
|
|
6308
7480
|
assertEconomyIdentifier(
|
|
@@ -6335,7 +7507,7 @@ function assertWalletActivityPage(page) {
|
|
|
6335
7507
|
"Activity pages are bounded and cannot advertise more rows from an empty page"
|
|
6336
7508
|
);
|
|
6337
7509
|
if (page.nextCursor !== void 0) {
|
|
6338
|
-
|
|
7510
|
+
assertOpaqueCursor2(page.nextCursor);
|
|
6339
7511
|
}
|
|
6340
7512
|
const activityIds = /* @__PURE__ */ new Set();
|
|
6341
7513
|
let previous;
|
|
@@ -7317,7 +8489,7 @@ var RESULT_OUTCOMES = /* @__PURE__ */ new Set([
|
|
|
7317
8489
|
"failed",
|
|
7318
8490
|
"no-op"
|
|
7319
8491
|
]);
|
|
7320
|
-
var
|
|
8492
|
+
var ACTIVITY_TYPES4 = /* @__PURE__ */ new Set([
|
|
7321
8493
|
"purchase",
|
|
7322
8494
|
"subscription",
|
|
7323
8495
|
"rewarded-ad",
|
|
@@ -7429,7 +8601,7 @@ var PORTABLE_KEYS = /* @__PURE__ */ new Set([
|
|
|
7429
8601
|
"signature",
|
|
7430
8602
|
...PORTABLE_BODY_KEYS
|
|
7431
8603
|
]);
|
|
7432
|
-
function
|
|
8604
|
+
function assertExactKeys5(value, allowedKeys, label) {
|
|
7433
8605
|
economyAssert(
|
|
7434
8606
|
value !== null && typeof value === "object" && !Array.isArray(value),
|
|
7435
8607
|
"INVALID_CONTRACT",
|
|
@@ -7518,7 +8690,7 @@ function canonicalSignatureMetadata(signature) {
|
|
|
7518
8690
|
};
|
|
7519
8691
|
}
|
|
7520
8692
|
function assertEconomySealedRecoveryPayload(payload) {
|
|
7521
|
-
|
|
8693
|
+
assertExactKeys5(
|
|
7522
8694
|
payload,
|
|
7523
8695
|
/* @__PURE__ */ new Set([
|
|
7524
8696
|
"schemaVersion",
|
|
@@ -7558,7 +8730,7 @@ function assertEconomySealedRecoveryPayload(payload) {
|
|
|
7558
8730
|
);
|
|
7559
8731
|
}
|
|
7560
8732
|
function assertAcceptanceBody(body) {
|
|
7561
|
-
|
|
8733
|
+
assertExactKeys5(
|
|
7562
8734
|
body,
|
|
7563
8735
|
"acceptanceEnvelopeId" in body ? ACCEPTANCE_KEYS : ACCEPTANCE_BODY_KEYS,
|
|
7564
8736
|
"Recovery acceptance body"
|
|
@@ -7627,7 +8799,7 @@ function createEconomyRecoveryAcceptanceEnvelope(body, hashCanonicalPayload2) {
|
|
|
7627
8799
|
};
|
|
7628
8800
|
}
|
|
7629
8801
|
function assertEconomyRecoveryAcceptanceEnvelope(envelope, hashCanonicalPayload2) {
|
|
7630
|
-
|
|
8802
|
+
assertExactKeys5(envelope, ACCEPTANCE_KEYS, "Recovery acceptance envelope");
|
|
7631
8803
|
assertAcceptanceBody(envelope);
|
|
7632
8804
|
assertEconomyIdentifier(
|
|
7633
8805
|
envelope.acceptanceEnvelopeId,
|
|
@@ -7668,7 +8840,7 @@ function canonicalEconomyRecoveryAcceptanceEnvelopePayload(envelope, hashCanonic
|
|
|
7668
8840
|
});
|
|
7669
8841
|
}
|
|
7670
8842
|
function assertCommittedResultBody(body) {
|
|
7671
|
-
|
|
8843
|
+
assertExactKeys5(
|
|
7672
8844
|
body,
|
|
7673
8845
|
"committedResultId" in body ? COMMITTED_RESULT_KEYS : COMMITTED_RESULT_BODY_KEYS,
|
|
7674
8846
|
"Recovery committed-result body"
|
|
@@ -7762,7 +8934,7 @@ function createEconomyRecoveryCommittedResult(body, hashCanonicalPayload2) {
|
|
|
7762
8934
|
};
|
|
7763
8935
|
}
|
|
7764
8936
|
function assertEconomyRecoveryCommittedResult(result, hashCanonicalPayload2) {
|
|
7765
|
-
|
|
8937
|
+
assertExactKeys5(
|
|
7766
8938
|
result,
|
|
7767
8939
|
COMMITTED_RESULT_KEYS,
|
|
7768
8940
|
"Recovery committed result"
|
|
@@ -7821,7 +8993,7 @@ function assertEconomyRecoveryResultLink(acceptance, result, hashCanonicalPayloa
|
|
|
7821
8993
|
);
|
|
7822
8994
|
}
|
|
7823
8995
|
function assertEconomyEvidenceSignatureMetadata(signature) {
|
|
7824
|
-
|
|
8996
|
+
assertExactKeys5(
|
|
7825
8997
|
signature,
|
|
7826
8998
|
/* @__PURE__ */ new Set([
|
|
7827
8999
|
"schemaVersion",
|
|
@@ -7841,7 +9013,7 @@ function assertEconomyEvidenceSignatureMetadata(signature) {
|
|
|
7841
9013
|
parseIsoTimestamp(signature.signedAt);
|
|
7842
9014
|
}
|
|
7843
9015
|
function assertEconomyEvidenceSignature(signature) {
|
|
7844
|
-
|
|
9016
|
+
assertExactKeys5(
|
|
7845
9017
|
signature,
|
|
7846
9018
|
/* @__PURE__ */ new Set([
|
|
7847
9019
|
"schemaVersion",
|
|
@@ -7863,7 +9035,7 @@ function assertEconomyEvidenceSignature(signature) {
|
|
|
7863
9035
|
assertBase64url(signature.value, "Evidence signature value", 32, 2048);
|
|
7864
9036
|
}
|
|
7865
9037
|
function assertRegionalEvidenceBody(body) {
|
|
7866
|
-
|
|
9038
|
+
assertExactKeys5(
|
|
7867
9039
|
body,
|
|
7868
9040
|
"evidenceReceiptId" in body ? REGIONAL_KEYS : REGIONAL_BODY_KEYS,
|
|
7869
9041
|
"Regional evidence-receipt body"
|
|
@@ -7955,7 +9127,7 @@ function createEconomyRegionalEvidenceReceipt(body, signature, hashCanonicalPayl
|
|
|
7955
9127
|
};
|
|
7956
9128
|
}
|
|
7957
9129
|
function assertEconomyRegionalEvidenceReceipt(receipt, hashCanonicalPayload2) {
|
|
7958
|
-
|
|
9130
|
+
assertExactKeys5(receipt, REGIONAL_KEYS, "Regional evidence receipt");
|
|
7959
9131
|
assertRegionalEvidenceBody(receipt);
|
|
7960
9132
|
assertEconomyIdentifier(receipt.evidenceReceiptId, "evidenceReceiptId");
|
|
7961
9133
|
assertEconomyEvidenceSignature(receipt.signature);
|
|
@@ -8157,7 +9329,7 @@ function assertEconomyRegionalEvidenceEquality(receipts, expectedRegions, hashCa
|
|
|
8157
9329
|
);
|
|
8158
9330
|
}
|
|
8159
9331
|
function assertEconomyMerkleInclusionProof(proof) {
|
|
8160
|
-
|
|
9332
|
+
assertExactKeys5(
|
|
8161
9333
|
proof,
|
|
8162
9334
|
/* @__PURE__ */ new Set([
|
|
8163
9335
|
"schemaVersion",
|
|
@@ -8188,7 +9360,7 @@ function assertEconomyMerkleInclusionProof(proof) {
|
|
|
8188
9360
|
"Merkle leaf position is outside its bounded tree"
|
|
8189
9361
|
);
|
|
8190
9362
|
for (const step of proof.siblings) {
|
|
8191
|
-
|
|
9363
|
+
assertExactKeys5(
|
|
8192
9364
|
step,
|
|
8193
9365
|
/* @__PURE__ */ new Set(["schemaVersion", "side", "hash"]),
|
|
8194
9366
|
"Merkle proof step"
|
|
@@ -8277,7 +9449,7 @@ function assertEconomyMerkleInclusion(proof, anchor, hashCanonicalPayload2) {
|
|
|
8277
9449
|
);
|
|
8278
9450
|
}
|
|
8279
9451
|
function assertPortableEvidenceReference(reference) {
|
|
8280
|
-
|
|
9452
|
+
assertExactKeys5(
|
|
8281
9453
|
reference,
|
|
8282
9454
|
/* @__PURE__ */ new Set([
|
|
8283
9455
|
"schemaVersion",
|
|
@@ -8314,7 +9486,7 @@ function canonicalPortableEvidenceReference(reference) {
|
|
|
8314
9486
|
};
|
|
8315
9487
|
}
|
|
8316
9488
|
function assertPortableBody(body) {
|
|
8317
|
-
|
|
9489
|
+
assertExactKeys5(
|
|
8318
9490
|
body,
|
|
8319
9491
|
"portableReceiptId" in body ? PORTABLE_KEYS : PORTABLE_BODY_KEYS,
|
|
8320
9492
|
"Portable customer-receipt body"
|
|
@@ -8338,7 +9510,7 @@ function assertPortableBody(body) {
|
|
|
8338
9510
|
assertEconomyIdentifier(value, label);
|
|
8339
9511
|
}
|
|
8340
9512
|
economyAssert(
|
|
8341
|
-
|
|
9513
|
+
ACTIVITY_TYPES4.has(body.activityType) && (body.direction === "credit" || body.direction === "debit"),
|
|
8342
9514
|
"INVALID_CONTRACT",
|
|
8343
9515
|
"Portable customer receipt has an unsupported activity or direction"
|
|
8344
9516
|
);
|
|
@@ -8438,7 +9610,7 @@ function createEconomyPortableCustomerReceipt(body, signature, hashCanonicalPayl
|
|
|
8438
9610
|
};
|
|
8439
9611
|
}
|
|
8440
9612
|
function assertEconomyPortableCustomerReceipt(receipt, hashCanonicalPayload2) {
|
|
8441
|
-
|
|
9613
|
+
assertExactKeys5(receipt, PORTABLE_KEYS, "Portable customer receipt");
|
|
8442
9614
|
assertPortableBody(receipt);
|
|
8443
9615
|
assertEconomyIdentifier(receipt.portableReceiptId, "portableReceiptId");
|
|
8444
9616
|
assertEconomyEvidenceSignature(receipt.signature);
|
|
@@ -8738,7 +9910,7 @@ var DOCUMENT_ID_KEYS = /* @__PURE__ */ new Set([
|
|
|
8738
9910
|
"lifetimeProjectionId",
|
|
8739
9911
|
"outboxEventId"
|
|
8740
9912
|
]);
|
|
8741
|
-
function
|
|
9913
|
+
function assertExactKeys6(value, allowed, label) {
|
|
8742
9914
|
economyAssert(
|
|
8743
9915
|
value !== null && typeof value === "object" && !Array.isArray(value),
|
|
8744
9916
|
"INVALID_CONTRACT",
|
|
@@ -8778,7 +9950,7 @@ function createPersonalWalletInitializationDocumentIds(subjectAccountId, hash) {
|
|
|
8778
9950
|
};
|
|
8779
9951
|
}
|
|
8780
9952
|
function assertPersonalWalletInitializationCommand(command) {
|
|
8781
|
-
|
|
9953
|
+
assertExactKeys6(command, COMMAND_KEYS, "Wallet initialization command");
|
|
8782
9954
|
economyAssert(
|
|
8783
9955
|
command.schemaVersion === ECONOMY_CONTRACT_VERSION && command.commandType === "initialize-wallet" && command.walletKind === "personal",
|
|
8784
9956
|
"INVALID_CONTRACT",
|
|
@@ -8802,7 +9974,7 @@ function canonicalPersonalWalletInitializationCommandPayload(command) {
|
|
|
8802
9974
|
});
|
|
8803
9975
|
}
|
|
8804
9976
|
function assertPersonalWalletInitializationOutboxIntent(intent) {
|
|
8805
|
-
|
|
9977
|
+
assertExactKeys6(intent, OUTBOX_KEYS, "Wallet initialization outbox intent");
|
|
8806
9978
|
economyAssert(
|
|
8807
9979
|
intent.schemaVersion === ECONOMY_CONTRACT_VERSION && intent.eventType === "wallet.initialized.v1",
|
|
8808
9980
|
"INVALID_CONTRACT",
|
|
@@ -8902,8 +10074,8 @@ function createPersonalWalletInitializationState(input, hash) {
|
|
|
8902
10074
|
return state;
|
|
8903
10075
|
}
|
|
8904
10076
|
function assertPersonalWalletInitializationState(state) {
|
|
8905
|
-
|
|
8906
|
-
|
|
10077
|
+
assertExactKeys6(state, STATE_KEYS, "Wallet initialization state");
|
|
10078
|
+
assertExactKeys6(
|
|
8907
10079
|
state.documentIds,
|
|
8908
10080
|
DOCUMENT_ID_KEYS,
|
|
8909
10081
|
"Wallet initialization document IDs"
|
|
@@ -8935,6 +10107,13 @@ function assertPersonalWalletInitializationState(state) {
|
|
|
8935
10107
|
}
|
|
8936
10108
|
// Annotate the CommonJS export names for ESM import in node:
|
|
8937
10109
|
0 && (module.exports = {
|
|
10110
|
+
ADMIN_TOKEN_ANOMALY_BASELINE_DAYS,
|
|
10111
|
+
ADMIN_TOKEN_DEFAULT_WINDOW_DAYS,
|
|
10112
|
+
ADMIN_TOKEN_MAXIMUM_HOURLY_WINDOW_DAYS,
|
|
10113
|
+
ADMIN_TOKEN_MAXIMUM_PAGE_SIZE,
|
|
10114
|
+
ADMIN_TOKEN_MAXIMUM_TREND_POINTS,
|
|
10115
|
+
ADMIN_TOKEN_MAXIMUM_WINDOW_DAYS,
|
|
10116
|
+
ADMIN_TOKEN_MINIMUM_COHORT_SIZE,
|
|
8938
10117
|
BASELINE_GBP_CATALOG_VERSION,
|
|
8939
10118
|
BASELINE_GBP_REFERENCE_RATE,
|
|
8940
10119
|
BASELINE_GBP_TOKEN_PACKS,
|
|
@@ -8962,6 +10141,19 @@ function assertPersonalWalletInitializationState(state) {
|
|
|
8962
10141
|
applyWalletBalanceDelta,
|
|
8963
10142
|
applyWalletLifetimeDeltas,
|
|
8964
10143
|
assertActivityEntry,
|
|
10144
|
+
assertAdminTokenActivityCursorBinding,
|
|
10145
|
+
assertAdminTokenActivityEntry,
|
|
10146
|
+
assertAdminTokenActivityPage,
|
|
10147
|
+
assertAdminTokenActivityPageForRequest,
|
|
10148
|
+
assertAdminTokenActivityPageRequest,
|
|
10149
|
+
assertAdminTokenEconomySummary,
|
|
10150
|
+
assertAdminTokenTrendRequest,
|
|
10151
|
+
assertAdminTokenTrendResult,
|
|
10152
|
+
assertAdminTokenTrendResultForRequest,
|
|
10153
|
+
assertAdminTokenWalletBalanceCursorBinding,
|
|
10154
|
+
assertAdminTokenWalletBalancePage,
|
|
10155
|
+
assertAdminTokenWalletBalancePageForRequest,
|
|
10156
|
+
assertAdminTokenWalletBalancePageRequest,
|
|
8965
10157
|
assertAuditedEconomyCommandEnvelope,
|
|
8966
10158
|
assertBalancedTransaction,
|
|
8967
10159
|
assertDeterministicWalletBalanceSummary,
|
|
@@ -9091,6 +10283,9 @@ function assertPersonalWalletInitializationState(state) {
|
|
|
9091
10283
|
canonicalTransactionPayload,
|
|
9092
10284
|
closeModuleAllowance,
|
|
9093
10285
|
convertRewardPayout,
|
|
10286
|
+
createAdminTokenAnomalyIndicator,
|
|
10287
|
+
createAdminTokenAnomalyUnavailable,
|
|
10288
|
+
createDefaultAdminTokenReportingWindow,
|
|
9094
10289
|
createEarlyBackerRetentionFromPaidLot,
|
|
9095
10290
|
createEconomyPortableCustomerReceipt,
|
|
9096
10291
|
createEconomyRecoveryAcceptanceEnvelope,
|