@plasius/economy 0.7.0 → 0.9.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 +68 -0
- package/dist/index.cjs +1263 -66
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +325 -2
- package/dist/index.d.ts +325 -2
- package/dist/index.js +1240 -66
- 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);
|
|
@@ -981,7 +2153,8 @@ var COMMAND_TYPES = /* @__PURE__ */ new Set([
|
|
|
981
2153
|
"chargeback",
|
|
982
2154
|
"reverse",
|
|
983
2155
|
"adjust",
|
|
984
|
-
"initialize-wallet"
|
|
2156
|
+
"initialize-wallet",
|
|
2157
|
+
"initialize-admin-reporting"
|
|
985
2158
|
]);
|
|
986
2159
|
var COMMAND_SOURCES = /* @__PURE__ */ new Set([
|
|
987
2160
|
"browser",
|
|
@@ -1045,6 +2218,7 @@ var SOURCE_COMMAND_TYPES = {
|
|
|
1045
2218
|
system: /* @__PURE__ */ new Set([
|
|
1046
2219
|
"credit-event",
|
|
1047
2220
|
"credit-competition",
|
|
2221
|
+
"initialize-admin-reporting",
|
|
1048
2222
|
"hold",
|
|
1049
2223
|
"release-hold",
|
|
1050
2224
|
"reverse"
|
|
@@ -1072,7 +2246,7 @@ var COMMAND_ENVELOPE_KEYS = /* @__PURE__ */ new Set([
|
|
|
1072
2246
|
"acceptedRegion",
|
|
1073
2247
|
"writerFencingToken"
|
|
1074
2248
|
]);
|
|
1075
|
-
function
|
|
2249
|
+
function assertExactKeys2(value, allowedKeys, label) {
|
|
1076
2250
|
economyAssert(
|
|
1077
2251
|
value !== null && typeof value === "object" && !Array.isArray(value),
|
|
1078
2252
|
"INVALID_CONTRACT",
|
|
@@ -1116,7 +2290,7 @@ function assertRelationshipContext(relationshipId, authorizationVersion) {
|
|
|
1116
2290
|
);
|
|
1117
2291
|
}
|
|
1118
2292
|
function assertEconomyHmacFingerprint(fingerprint, expectedDomain) {
|
|
1119
|
-
|
|
2293
|
+
assertExactKeys2(
|
|
1120
2294
|
fingerprint,
|
|
1121
2295
|
/* @__PURE__ */ new Set([
|
|
1122
2296
|
"schemaVersion",
|
|
@@ -1141,7 +2315,7 @@ function assertEconomyHmacFingerprint(fingerprint, expectedDomain) {
|
|
|
1141
2315
|
);
|
|
1142
2316
|
}
|
|
1143
2317
|
function assertEconomyAuthorizationEvidence(evidence) {
|
|
1144
|
-
|
|
2318
|
+
assertExactKeys2(
|
|
1145
2319
|
evidence,
|
|
1146
2320
|
/* @__PURE__ */ new Set([
|
|
1147
2321
|
"schemaVersion",
|
|
@@ -1178,7 +2352,7 @@ function assertEconomyAuthorizationEvidence(evidence) {
|
|
|
1178
2352
|
);
|
|
1179
2353
|
}
|
|
1180
2354
|
function assertCausationReference(causation) {
|
|
1181
|
-
|
|
2355
|
+
assertExactKeys2(
|
|
1182
2356
|
causation,
|
|
1183
2357
|
/* @__PURE__ */ new Set(["schemaVersion", "kind", "causationId"]),
|
|
1184
2358
|
"Economy causation reference"
|
|
@@ -1233,7 +2407,7 @@ function assertCommandSourcePrincipal(envelope) {
|
|
|
1233
2407
|
}
|
|
1234
2408
|
}
|
|
1235
2409
|
function assertAuditedEconomyCommandEnvelope(envelope) {
|
|
1236
|
-
|
|
2410
|
+
assertExactKeys2(
|
|
1237
2411
|
envelope,
|
|
1238
2412
|
COMMAND_ENVELOPE_KEYS,
|
|
1239
2413
|
"Audited economy command envelope"
|
|
@@ -1299,7 +2473,7 @@ function assertAuditedEconomyCommandEnvelope(envelope) {
|
|
|
1299
2473
|
);
|
|
1300
2474
|
}
|
|
1301
2475
|
function assertEconomyProviderEvidenceHash(evidence) {
|
|
1302
|
-
|
|
2476
|
+
assertExactKeys2(
|
|
1303
2477
|
evidence,
|
|
1304
2478
|
/* @__PURE__ */ new Set([
|
|
1305
2479
|
"schemaVersion",
|
|
@@ -1370,7 +2544,7 @@ function assertEconomyProviderEvidenceHash(evidence) {
|
|
|
1370
2544
|
}
|
|
1371
2545
|
}
|
|
1372
2546
|
function assertEconomyEncryptedOperationalHandleBinding(binding) {
|
|
1373
|
-
|
|
2547
|
+
assertExactKeys2(
|
|
1374
2548
|
binding,
|
|
1375
2549
|
/* @__PURE__ */ new Set([
|
|
1376
2550
|
"schemaVersion",
|
|
@@ -1405,7 +2579,7 @@ function assertEconomyEncryptedOperationalHandleBinding(binding) {
|
|
|
1405
2579
|
parseIsoTimestamp(binding.createdAt);
|
|
1406
2580
|
}
|
|
1407
2581
|
function assertEvidenceRecordReference(reference) {
|
|
1408
|
-
|
|
2582
|
+
assertExactKeys2(
|
|
1409
2583
|
reference,
|
|
1410
2584
|
/* @__PURE__ */ new Set(["schemaVersion", "recordId", "contentHash"]),
|
|
1411
2585
|
"Evidence record reference"
|
|
@@ -1436,7 +2610,7 @@ function assertUniqueSortedReferences(references, label) {
|
|
|
1436
2610
|
}
|
|
1437
2611
|
}
|
|
1438
2612
|
function assertEconomyProviderEvidenceManifest(manifest) {
|
|
1439
|
-
|
|
2613
|
+
assertExactKeys2(
|
|
1440
2614
|
manifest,
|
|
1441
2615
|
/* @__PURE__ */ new Set([
|
|
1442
2616
|
"schemaVersion",
|
|
@@ -1478,7 +2652,7 @@ function assertEconomyProviderEvidenceManifest(manifest) {
|
|
|
1478
2652
|
parseIsoTimestamp(manifest.createdAt);
|
|
1479
2653
|
}
|
|
1480
2654
|
function assertEconomyAcceptedCommandReceipt(receipt) {
|
|
1481
|
-
|
|
2655
|
+
assertExactKeys2(
|
|
1482
2656
|
receipt,
|
|
1483
2657
|
/* @__PURE__ */ new Set([
|
|
1484
2658
|
"schemaVersion",
|
|
@@ -1502,7 +2676,7 @@ function assertEconomyAcceptedCommandReceipt(receipt) {
|
|
|
1502
2676
|
parseIsoTimestamp(receipt.acceptedAt);
|
|
1503
2677
|
}
|
|
1504
2678
|
function assertEconomyCommandResultReceipt(receipt) {
|
|
1505
|
-
|
|
2679
|
+
assertExactKeys2(
|
|
1506
2680
|
receipt,
|
|
1507
2681
|
/* @__PURE__ */ new Set([
|
|
1508
2682
|
"schemaVersion",
|
|
@@ -1559,7 +2733,7 @@ function assertEconomyCommandResultReceipt(receipt) {
|
|
|
1559
2733
|
}
|
|
1560
2734
|
}
|
|
1561
2735
|
function assertEconomyAuditedIdempotencyScope(scope) {
|
|
1562
|
-
|
|
2736
|
+
assertExactKeys2(
|
|
1563
2737
|
scope,
|
|
1564
2738
|
/* @__PURE__ */ new Set([
|
|
1565
2739
|
"schemaVersion",
|
|
@@ -1590,7 +2764,7 @@ function assertEconomyAuditedIdempotencyScope(scope) {
|
|
|
1590
2764
|
);
|
|
1591
2765
|
}
|
|
1592
2766
|
function assertEconomyAuditedIdempotencyResult(result) {
|
|
1593
|
-
|
|
2767
|
+
assertExactKeys2(
|
|
1594
2768
|
result,
|
|
1595
2769
|
/* @__PURE__ */ new Set([
|
|
1596
2770
|
"schemaVersion",
|
|
@@ -1881,7 +3055,7 @@ var MANIFEST_KEYS = /* @__PURE__ */ new Set([
|
|
|
1881
3055
|
"recordReferences",
|
|
1882
3056
|
"committedAt"
|
|
1883
3057
|
]);
|
|
1884
|
-
function
|
|
3058
|
+
function assertExactKeys3(value, allowedKeys, label) {
|
|
1885
3059
|
economyAssert(
|
|
1886
3060
|
value !== null && typeof value === "object" && !Array.isArray(value),
|
|
1887
3061
|
"INVALID_CONTRACT",
|
|
@@ -1919,7 +3093,7 @@ function referenceOrder(left, right) {
|
|
|
1919
3093
|
return byKind === 0 ? compareUnicodeCodeUnits(left.recordId, right.recordId) : byKind;
|
|
1920
3094
|
}
|
|
1921
3095
|
function assertEconomyAuthorityRecordReference(reference) {
|
|
1922
|
-
|
|
3096
|
+
assertExactKeys3(
|
|
1923
3097
|
reference,
|
|
1924
3098
|
/* @__PURE__ */ new Set([
|
|
1925
3099
|
"schemaVersion",
|
|
@@ -2083,7 +3257,7 @@ function assertCommitAllowedInState(manifest) {
|
|
|
2083
3257
|
}
|
|
2084
3258
|
}
|
|
2085
3259
|
function assertEconomyAuthorityCommitManifest(manifest) {
|
|
2086
|
-
|
|
3260
|
+
assertExactKeys3(manifest, MANIFEST_KEYS, "Authority commit manifest");
|
|
2087
3261
|
economyAssert(
|
|
2088
3262
|
manifest.schemaVersion === ECONOMY_CONTRACT_VERSION && COMMIT_KINDS.has(manifest.commitKind) && AUTHORITY_STATES.has(manifest.authorityStateBefore) && AUTHORITY_STATES.has(manifest.authorityStateAfter),
|
|
2089
3263
|
"INVALID_CONTRACT",
|
|
@@ -2130,7 +3304,7 @@ function assertEconomyAuthorityCommitManifest(manifest) {
|
|
|
2130
3304
|
parseIsoTimestamp(manifest.committedAt);
|
|
2131
3305
|
}
|
|
2132
3306
|
function assertEconomyAuthorityHead(head) {
|
|
2133
|
-
|
|
3307
|
+
assertExactKeys3(head, HEAD_KEYS, "Economy authority head");
|
|
2134
3308
|
economyAssert(
|
|
2135
3309
|
head.schemaVersion === ECONOMY_CONTRACT_VERSION && AUTHORITY_STATES.has(head.state),
|
|
2136
3310
|
"INVALID_CONTRACT",
|
|
@@ -2189,7 +3363,7 @@ function advanceEconomyAuthorityHead(head, manifest, manifestCanonicalHash) {
|
|
|
2189
3363
|
};
|
|
2190
3364
|
}
|
|
2191
3365
|
function assertEconomyIntegrityVerificationReceipt(receipt) {
|
|
2192
|
-
|
|
3366
|
+
assertExactKeys3(
|
|
2193
3367
|
receipt,
|
|
2194
3368
|
/* @__PURE__ */ new Set([
|
|
2195
3369
|
"schemaVersion",
|
|
@@ -2335,7 +3509,7 @@ function assertEconomyIntegrityVerificationReceipt(receipt) {
|
|
|
2335
3509
|
parseIsoTimestamp(receipt.verifiedAt);
|
|
2336
3510
|
}
|
|
2337
3511
|
function assertEconomyIntegrityAnchorManifest(manifest) {
|
|
2338
|
-
|
|
3512
|
+
assertExactKeys3(
|
|
2339
3513
|
manifest,
|
|
2340
3514
|
/* @__PURE__ */ new Set([
|
|
2341
3515
|
"schemaVersion",
|
|
@@ -2497,7 +3671,7 @@ function sortEconomyAuthorityRecordReferences(references) {
|
|
|
2497
3671
|
}
|
|
2498
3672
|
|
|
2499
3673
|
// src/ledger.ts
|
|
2500
|
-
var
|
|
3674
|
+
var ACTIVITY_TYPES2 = /* @__PURE__ */ new Set([
|
|
2501
3675
|
"purchase",
|
|
2502
3676
|
"subscription",
|
|
2503
3677
|
"rewarded-ad",
|
|
@@ -2514,14 +3688,14 @@ var ACTIVITY_TYPES = /* @__PURE__ */ new Set([
|
|
|
2514
3688
|
"event",
|
|
2515
3689
|
"competition"
|
|
2516
3690
|
]);
|
|
2517
|
-
var
|
|
3691
|
+
var ACTIVITY_STATUSES2 = /* @__PURE__ */ new Set([
|
|
2518
3692
|
"pending",
|
|
2519
3693
|
"held",
|
|
2520
3694
|
"settled",
|
|
2521
3695
|
"reversed",
|
|
2522
3696
|
"failed"
|
|
2523
3697
|
]);
|
|
2524
|
-
var
|
|
3698
|
+
var ACTIVITY_SOURCES2 = /* @__PURE__ */ new Set([
|
|
2525
3699
|
"shopify",
|
|
2526
3700
|
"ayet",
|
|
2527
3701
|
"bitlabs",
|
|
@@ -2551,7 +3725,7 @@ function assertActivityEntry(entry) {
|
|
|
2551
3725
|
);
|
|
2552
3726
|
assertEconomyIdentifier(entry.transactionId, "transactionId");
|
|
2553
3727
|
economyAssert(
|
|
2554
|
-
|
|
3728
|
+
ACTIVITY_TYPES2.has(entry.activityType) && ACTIVITY_STATUSES2.has(entry.status) && ACTIVITY_SOURCES2.has(entry.source),
|
|
2555
3729
|
"INVALID_CONTRACT",
|
|
2556
3730
|
"Activity type, status, or source is unsupported"
|
|
2557
3731
|
);
|
|
@@ -2589,7 +3763,7 @@ function assertBalancedTransaction(transaction) {
|
|
|
2589
3763
|
assertEconomyIdentifier(transaction.transactionId, "transactionId");
|
|
2590
3764
|
assertEconomyIdentifier(transaction.idempotencyKey, "idempotencyKey");
|
|
2591
3765
|
economyAssert(
|
|
2592
|
-
|
|
3766
|
+
ACTIVITY_TYPES2.has(transaction.activityType) && ACTIVITY_STATUSES2.has(transaction.status),
|
|
2593
3767
|
"INVALID_CONTRACT",
|
|
2594
3768
|
"Transaction activity type or status is unsupported"
|
|
2595
3769
|
);
|
|
@@ -4628,7 +5802,7 @@ var DECISIONS = /* @__PURE__ */ new Set([
|
|
|
4628
5802
|
"approve",
|
|
4629
5803
|
"reject"
|
|
4630
5804
|
]);
|
|
4631
|
-
function
|
|
5805
|
+
function assertExactKeys4(value, allowed, label) {
|
|
4632
5806
|
economyAssert(
|
|
4633
5807
|
value !== null && typeof value === "object" && !Array.isArray(value),
|
|
4634
5808
|
"INVALID_CONTRACT",
|
|
@@ -4655,7 +5829,7 @@ function assertReasonCode(reasonCode) {
|
|
|
4655
5829
|
);
|
|
4656
5830
|
}
|
|
4657
5831
|
function assertOperatorAdjustmentPreview(preview) {
|
|
4658
|
-
|
|
5832
|
+
assertExactKeys4(preview, PREVIEW_KEYS, "Operator adjustment preview");
|
|
4659
5833
|
economyAssert(
|
|
4660
5834
|
preview.schemaVersion === ECONOMY_CONTRACT_VERSION && OPERATIONS.has(preview.operation) && TARGET_COMPONENTS.has(preview.targetComponent) && TRANSFER_POLICIES.has(preview.transferPolicy) && preview.refundPolicy === "not-refundable",
|
|
4661
5835
|
"INVALID_CONTRACT",
|
|
@@ -4734,7 +5908,7 @@ function canonicalOperatorAdjustmentPreviewPayload(preview) {
|
|
|
4734
5908
|
function assertOperatorAdjustmentProposal(proposal, preview, expectedPreviewHash) {
|
|
4735
5909
|
assertOperatorAdjustmentPreview(preview);
|
|
4736
5910
|
assertCanonicalHash6(expectedPreviewHash, "expectedPreviewHash");
|
|
4737
|
-
|
|
5911
|
+
assertExactKeys4(proposal, PROPOSAL_KEYS, "Operator adjustment proposal");
|
|
4738
5912
|
economyAssert(
|
|
4739
5913
|
proposal.schemaVersion === ECONOMY_CONTRACT_VERSION && proposal.status === "pending-approval",
|
|
4740
5914
|
"INVALID_CONTRACT",
|
|
@@ -4761,7 +5935,7 @@ function assertOperatorAdjustmentProposal(proposal, preview, expectedPreviewHash
|
|
|
4761
5935
|
);
|
|
4762
5936
|
}
|
|
4763
5937
|
function canonicalOperatorAdjustmentProposalPayload(proposal) {
|
|
4764
|
-
|
|
5938
|
+
assertExactKeys4(proposal, PROPOSAL_KEYS, "Operator adjustment proposal");
|
|
4765
5939
|
return JSON.stringify({
|
|
4766
5940
|
schemaVersion: proposal.schemaVersion,
|
|
4767
5941
|
proposalId: proposal.proposalId,
|
|
@@ -4776,7 +5950,7 @@ function canonicalOperatorAdjustmentProposalPayload(proposal) {
|
|
|
4776
5950
|
function assertOperatorAdjustmentDecision(decision, proposal, preview, expectedPreviewHash, expectedProposalHash) {
|
|
4777
5951
|
assertOperatorAdjustmentProposal(proposal, preview, expectedPreviewHash);
|
|
4778
5952
|
assertCanonicalHash6(expectedProposalHash, "expectedProposalHash");
|
|
4779
|
-
|
|
5953
|
+
assertExactKeys4(decision, DECISION_KEYS, "Operator adjustment decision");
|
|
4780
5954
|
economyAssert(
|
|
4781
5955
|
decision.schemaVersion === ECONOMY_CONTRACT_VERSION && DECISIONS.has(decision.decision),
|
|
4782
5956
|
"INVALID_CONTRACT",
|
|
@@ -4819,7 +5993,7 @@ function assertOperatorAdjustmentDecision(decision, proposal, preview, expectedP
|
|
|
4819
5993
|
);
|
|
4820
5994
|
}
|
|
4821
5995
|
function canonicalOperatorAdjustmentDecisionPayload(decision) {
|
|
4822
|
-
|
|
5996
|
+
assertExactKeys4(decision, DECISION_KEYS, "Operator adjustment decision");
|
|
4823
5997
|
return JSON.stringify({
|
|
4824
5998
|
schemaVersion: decision.schemaVersion,
|
|
4825
5999
|
decisionId: decision.decisionId,
|
|
@@ -4843,7 +6017,7 @@ function assertOperatorAdjustmentExecution(execution, preview, proposal, decisio
|
|
|
4843
6017
|
expectedProposalHash
|
|
4844
6018
|
);
|
|
4845
6019
|
assertCanonicalHash6(expectedDecisionHash, "expectedDecisionHash");
|
|
4846
|
-
|
|
6020
|
+
assertExactKeys4(execution, EXECUTION_KEYS, "Operator adjustment execution");
|
|
4847
6021
|
economyAssert(
|
|
4848
6022
|
execution.schemaVersion === ECONOMY_CONTRACT_VERSION,
|
|
4849
6023
|
"INVALID_CONTRACT",
|
|
@@ -4874,7 +6048,7 @@ function assertOperatorAdjustmentExecution(execution, preview, proposal, decisio
|
|
|
4874
6048
|
);
|
|
4875
6049
|
}
|
|
4876
6050
|
function canonicalOperatorAdjustmentExecutionPayload(execution) {
|
|
4877
|
-
|
|
6051
|
+
assertExactKeys4(execution, EXECUTION_KEYS, "Operator adjustment execution");
|
|
4878
6052
|
return JSON.stringify({
|
|
4879
6053
|
schemaVersion: execution.schemaVersion,
|
|
4880
6054
|
executionId: execution.executionId,
|
|
@@ -5919,7 +7093,7 @@ function createProjectionSnapshot(transactions, rebuiltAt) {
|
|
|
5919
7093
|
}
|
|
5920
7094
|
|
|
5921
7095
|
// src/ports/query.ts
|
|
5922
|
-
var
|
|
7096
|
+
var ACTIVITY_TYPES3 = /* @__PURE__ */ new Set([
|
|
5923
7097
|
"purchase",
|
|
5924
7098
|
"subscription",
|
|
5925
7099
|
"rewarded-ad",
|
|
@@ -5936,14 +7110,14 @@ var ACTIVITY_TYPES2 = /* @__PURE__ */ new Set([
|
|
|
5936
7110
|
"event",
|
|
5937
7111
|
"competition"
|
|
5938
7112
|
]);
|
|
5939
|
-
var
|
|
7113
|
+
var ACTIVITY_STATUSES3 = /* @__PURE__ */ new Set([
|
|
5940
7114
|
"pending",
|
|
5941
7115
|
"held",
|
|
5942
7116
|
"settled",
|
|
5943
7117
|
"reversed",
|
|
5944
7118
|
"failed"
|
|
5945
7119
|
]);
|
|
5946
|
-
var
|
|
7120
|
+
var ACTIVITY_SOURCES3 = /* @__PURE__ */ new Set([
|
|
5947
7121
|
"shopify",
|
|
5948
7122
|
"ayet",
|
|
5949
7123
|
"bitlabs",
|
|
@@ -5971,14 +7145,14 @@ function assertSafeDisplayString(value, label) {
|
|
|
5971
7145
|
`${label} must be bounded and safe for display`
|
|
5972
7146
|
);
|
|
5973
7147
|
}
|
|
5974
|
-
function
|
|
7148
|
+
function assertOpaqueCursor2(value) {
|
|
5975
7149
|
economyAssert(
|
|
5976
7150
|
typeof value === "string" && value.length > 0 && value.length <= 512 && !hasControlCharacters2(value),
|
|
5977
7151
|
"INVALID_CONTRACT",
|
|
5978
7152
|
"Activity cursor must be a bounded opaque value"
|
|
5979
7153
|
);
|
|
5980
7154
|
}
|
|
5981
|
-
function
|
|
7155
|
+
function assertUniqueValues2(values, allowed, label) {
|
|
5982
7156
|
const unique = new Set(values);
|
|
5983
7157
|
economyAssert(
|
|
5984
7158
|
values.length > 0 && values.length === unique.size && values.every((value) => allowed.has(value)),
|
|
@@ -6241,7 +7415,7 @@ function assertWalletActivityEntry(entry) {
|
|
|
6241
7415
|
assertEconomyIdentifier(entry.activityId, "activityId");
|
|
6242
7416
|
assertEconomyIdentifier(entry.walletId, "walletId");
|
|
6243
7417
|
economyAssert(
|
|
6244
|
-
|
|
7418
|
+
ACTIVITY_TYPES3.has(entry.activityType) && ACTIVITY_STATUSES3.has(entry.status) && ACTIVITY_SOURCES3.has(entry.source),
|
|
6245
7419
|
"INVALID_CONTRACT",
|
|
6246
7420
|
"Wallet activity type, status, or source is unsupported"
|
|
6247
7421
|
);
|
|
@@ -6289,20 +7463,20 @@ function assertWalletActivityPageRequest(request) {
|
|
|
6289
7463
|
"Activity page limit must be between one and 100"
|
|
6290
7464
|
);
|
|
6291
7465
|
if (request.cursor !== void 0) {
|
|
6292
|
-
|
|
7466
|
+
assertOpaqueCursor2(request.cursor);
|
|
6293
7467
|
}
|
|
6294
7468
|
const filter = request.filter;
|
|
6295
7469
|
if (filter === void 0) {
|
|
6296
7470
|
return;
|
|
6297
7471
|
}
|
|
6298
7472
|
if (filter.activityTypes !== void 0) {
|
|
6299
|
-
|
|
7473
|
+
assertUniqueValues2(filter.activityTypes, ACTIVITY_TYPES3, "Activity types");
|
|
6300
7474
|
}
|
|
6301
7475
|
if (filter.statuses !== void 0) {
|
|
6302
|
-
|
|
7476
|
+
assertUniqueValues2(filter.statuses, ACTIVITY_STATUSES3, "Activity statuses");
|
|
6303
7477
|
}
|
|
6304
7478
|
if (filter.sources !== void 0) {
|
|
6305
|
-
|
|
7479
|
+
assertUniqueValues2(filter.sources, ACTIVITY_SOURCES3, "Activity sources");
|
|
6306
7480
|
}
|
|
6307
7481
|
if (filter.beneficiaryAccountId !== void 0) {
|
|
6308
7482
|
assertEconomyIdentifier(
|
|
@@ -6335,7 +7509,7 @@ function assertWalletActivityPage(page) {
|
|
|
6335
7509
|
"Activity pages are bounded and cannot advertise more rows from an empty page"
|
|
6336
7510
|
);
|
|
6337
7511
|
if (page.nextCursor !== void 0) {
|
|
6338
|
-
|
|
7512
|
+
assertOpaqueCursor2(page.nextCursor);
|
|
6339
7513
|
}
|
|
6340
7514
|
const activityIds = /* @__PURE__ */ new Set();
|
|
6341
7515
|
let previous;
|
|
@@ -7317,7 +8491,7 @@ var RESULT_OUTCOMES = /* @__PURE__ */ new Set([
|
|
|
7317
8491
|
"failed",
|
|
7318
8492
|
"no-op"
|
|
7319
8493
|
]);
|
|
7320
|
-
var
|
|
8494
|
+
var ACTIVITY_TYPES4 = /* @__PURE__ */ new Set([
|
|
7321
8495
|
"purchase",
|
|
7322
8496
|
"subscription",
|
|
7323
8497
|
"rewarded-ad",
|
|
@@ -7429,7 +8603,7 @@ var PORTABLE_KEYS = /* @__PURE__ */ new Set([
|
|
|
7429
8603
|
"signature",
|
|
7430
8604
|
...PORTABLE_BODY_KEYS
|
|
7431
8605
|
]);
|
|
7432
|
-
function
|
|
8606
|
+
function assertExactKeys5(value, allowedKeys, label) {
|
|
7433
8607
|
economyAssert(
|
|
7434
8608
|
value !== null && typeof value === "object" && !Array.isArray(value),
|
|
7435
8609
|
"INVALID_CONTRACT",
|
|
@@ -7518,7 +8692,7 @@ function canonicalSignatureMetadata(signature) {
|
|
|
7518
8692
|
};
|
|
7519
8693
|
}
|
|
7520
8694
|
function assertEconomySealedRecoveryPayload(payload) {
|
|
7521
|
-
|
|
8695
|
+
assertExactKeys5(
|
|
7522
8696
|
payload,
|
|
7523
8697
|
/* @__PURE__ */ new Set([
|
|
7524
8698
|
"schemaVersion",
|
|
@@ -7558,7 +8732,7 @@ function assertEconomySealedRecoveryPayload(payload) {
|
|
|
7558
8732
|
);
|
|
7559
8733
|
}
|
|
7560
8734
|
function assertAcceptanceBody(body) {
|
|
7561
|
-
|
|
8735
|
+
assertExactKeys5(
|
|
7562
8736
|
body,
|
|
7563
8737
|
"acceptanceEnvelopeId" in body ? ACCEPTANCE_KEYS : ACCEPTANCE_BODY_KEYS,
|
|
7564
8738
|
"Recovery acceptance body"
|
|
@@ -7627,7 +8801,7 @@ function createEconomyRecoveryAcceptanceEnvelope(body, hashCanonicalPayload2) {
|
|
|
7627
8801
|
};
|
|
7628
8802
|
}
|
|
7629
8803
|
function assertEconomyRecoveryAcceptanceEnvelope(envelope, hashCanonicalPayload2) {
|
|
7630
|
-
|
|
8804
|
+
assertExactKeys5(envelope, ACCEPTANCE_KEYS, "Recovery acceptance envelope");
|
|
7631
8805
|
assertAcceptanceBody(envelope);
|
|
7632
8806
|
assertEconomyIdentifier(
|
|
7633
8807
|
envelope.acceptanceEnvelopeId,
|
|
@@ -7668,7 +8842,7 @@ function canonicalEconomyRecoveryAcceptanceEnvelopePayload(envelope, hashCanonic
|
|
|
7668
8842
|
});
|
|
7669
8843
|
}
|
|
7670
8844
|
function assertCommittedResultBody(body) {
|
|
7671
|
-
|
|
8845
|
+
assertExactKeys5(
|
|
7672
8846
|
body,
|
|
7673
8847
|
"committedResultId" in body ? COMMITTED_RESULT_KEYS : COMMITTED_RESULT_BODY_KEYS,
|
|
7674
8848
|
"Recovery committed-result body"
|
|
@@ -7762,7 +8936,7 @@ function createEconomyRecoveryCommittedResult(body, hashCanonicalPayload2) {
|
|
|
7762
8936
|
};
|
|
7763
8937
|
}
|
|
7764
8938
|
function assertEconomyRecoveryCommittedResult(result, hashCanonicalPayload2) {
|
|
7765
|
-
|
|
8939
|
+
assertExactKeys5(
|
|
7766
8940
|
result,
|
|
7767
8941
|
COMMITTED_RESULT_KEYS,
|
|
7768
8942
|
"Recovery committed result"
|
|
@@ -7821,7 +8995,7 @@ function assertEconomyRecoveryResultLink(acceptance, result, hashCanonicalPayloa
|
|
|
7821
8995
|
);
|
|
7822
8996
|
}
|
|
7823
8997
|
function assertEconomyEvidenceSignatureMetadata(signature) {
|
|
7824
|
-
|
|
8998
|
+
assertExactKeys5(
|
|
7825
8999
|
signature,
|
|
7826
9000
|
/* @__PURE__ */ new Set([
|
|
7827
9001
|
"schemaVersion",
|
|
@@ -7841,7 +9015,7 @@ function assertEconomyEvidenceSignatureMetadata(signature) {
|
|
|
7841
9015
|
parseIsoTimestamp(signature.signedAt);
|
|
7842
9016
|
}
|
|
7843
9017
|
function assertEconomyEvidenceSignature(signature) {
|
|
7844
|
-
|
|
9018
|
+
assertExactKeys5(
|
|
7845
9019
|
signature,
|
|
7846
9020
|
/* @__PURE__ */ new Set([
|
|
7847
9021
|
"schemaVersion",
|
|
@@ -7863,7 +9037,7 @@ function assertEconomyEvidenceSignature(signature) {
|
|
|
7863
9037
|
assertBase64url(signature.value, "Evidence signature value", 32, 2048);
|
|
7864
9038
|
}
|
|
7865
9039
|
function assertRegionalEvidenceBody(body) {
|
|
7866
|
-
|
|
9040
|
+
assertExactKeys5(
|
|
7867
9041
|
body,
|
|
7868
9042
|
"evidenceReceiptId" in body ? REGIONAL_KEYS : REGIONAL_BODY_KEYS,
|
|
7869
9043
|
"Regional evidence-receipt body"
|
|
@@ -7955,7 +9129,7 @@ function createEconomyRegionalEvidenceReceipt(body, signature, hashCanonicalPayl
|
|
|
7955
9129
|
};
|
|
7956
9130
|
}
|
|
7957
9131
|
function assertEconomyRegionalEvidenceReceipt(receipt, hashCanonicalPayload2) {
|
|
7958
|
-
|
|
9132
|
+
assertExactKeys5(receipt, REGIONAL_KEYS, "Regional evidence receipt");
|
|
7959
9133
|
assertRegionalEvidenceBody(receipt);
|
|
7960
9134
|
assertEconomyIdentifier(receipt.evidenceReceiptId, "evidenceReceiptId");
|
|
7961
9135
|
assertEconomyEvidenceSignature(receipt.signature);
|
|
@@ -8157,7 +9331,7 @@ function assertEconomyRegionalEvidenceEquality(receipts, expectedRegions, hashCa
|
|
|
8157
9331
|
);
|
|
8158
9332
|
}
|
|
8159
9333
|
function assertEconomyMerkleInclusionProof(proof) {
|
|
8160
|
-
|
|
9334
|
+
assertExactKeys5(
|
|
8161
9335
|
proof,
|
|
8162
9336
|
/* @__PURE__ */ new Set([
|
|
8163
9337
|
"schemaVersion",
|
|
@@ -8188,7 +9362,7 @@ function assertEconomyMerkleInclusionProof(proof) {
|
|
|
8188
9362
|
"Merkle leaf position is outside its bounded tree"
|
|
8189
9363
|
);
|
|
8190
9364
|
for (const step of proof.siblings) {
|
|
8191
|
-
|
|
9365
|
+
assertExactKeys5(
|
|
8192
9366
|
step,
|
|
8193
9367
|
/* @__PURE__ */ new Set(["schemaVersion", "side", "hash"]),
|
|
8194
9368
|
"Merkle proof step"
|
|
@@ -8277,7 +9451,7 @@ function assertEconomyMerkleInclusion(proof, anchor, hashCanonicalPayload2) {
|
|
|
8277
9451
|
);
|
|
8278
9452
|
}
|
|
8279
9453
|
function assertPortableEvidenceReference(reference) {
|
|
8280
|
-
|
|
9454
|
+
assertExactKeys5(
|
|
8281
9455
|
reference,
|
|
8282
9456
|
/* @__PURE__ */ new Set([
|
|
8283
9457
|
"schemaVersion",
|
|
@@ -8314,7 +9488,7 @@ function canonicalPortableEvidenceReference(reference) {
|
|
|
8314
9488
|
};
|
|
8315
9489
|
}
|
|
8316
9490
|
function assertPortableBody(body) {
|
|
8317
|
-
|
|
9491
|
+
assertExactKeys5(
|
|
8318
9492
|
body,
|
|
8319
9493
|
"portableReceiptId" in body ? PORTABLE_KEYS : PORTABLE_BODY_KEYS,
|
|
8320
9494
|
"Portable customer-receipt body"
|
|
@@ -8338,7 +9512,7 @@ function assertPortableBody(body) {
|
|
|
8338
9512
|
assertEconomyIdentifier(value, label);
|
|
8339
9513
|
}
|
|
8340
9514
|
economyAssert(
|
|
8341
|
-
|
|
9515
|
+
ACTIVITY_TYPES4.has(body.activityType) && (body.direction === "credit" || body.direction === "debit"),
|
|
8342
9516
|
"INVALID_CONTRACT",
|
|
8343
9517
|
"Portable customer receipt has an unsupported activity or direction"
|
|
8344
9518
|
);
|
|
@@ -8438,7 +9612,7 @@ function createEconomyPortableCustomerReceipt(body, signature, hashCanonicalPayl
|
|
|
8438
9612
|
};
|
|
8439
9613
|
}
|
|
8440
9614
|
function assertEconomyPortableCustomerReceipt(receipt, hashCanonicalPayload2) {
|
|
8441
|
-
|
|
9615
|
+
assertExactKeys5(receipt, PORTABLE_KEYS, "Portable customer receipt");
|
|
8442
9616
|
assertPortableBody(receipt);
|
|
8443
9617
|
assertEconomyIdentifier(receipt.portableReceiptId, "portableReceiptId");
|
|
8444
9618
|
assertEconomyEvidenceSignature(receipt.signature);
|
|
@@ -8738,7 +9912,7 @@ var DOCUMENT_ID_KEYS = /* @__PURE__ */ new Set([
|
|
|
8738
9912
|
"lifetimeProjectionId",
|
|
8739
9913
|
"outboxEventId"
|
|
8740
9914
|
]);
|
|
8741
|
-
function
|
|
9915
|
+
function assertExactKeys6(value, allowed, label) {
|
|
8742
9916
|
economyAssert(
|
|
8743
9917
|
value !== null && typeof value === "object" && !Array.isArray(value),
|
|
8744
9918
|
"INVALID_CONTRACT",
|
|
@@ -8778,7 +9952,7 @@ function createPersonalWalletInitializationDocumentIds(subjectAccountId, hash) {
|
|
|
8778
9952
|
};
|
|
8779
9953
|
}
|
|
8780
9954
|
function assertPersonalWalletInitializationCommand(command) {
|
|
8781
|
-
|
|
9955
|
+
assertExactKeys6(command, COMMAND_KEYS, "Wallet initialization command");
|
|
8782
9956
|
economyAssert(
|
|
8783
9957
|
command.schemaVersion === ECONOMY_CONTRACT_VERSION && command.commandType === "initialize-wallet" && command.walletKind === "personal",
|
|
8784
9958
|
"INVALID_CONTRACT",
|
|
@@ -8802,7 +9976,7 @@ function canonicalPersonalWalletInitializationCommandPayload(command) {
|
|
|
8802
9976
|
});
|
|
8803
9977
|
}
|
|
8804
9978
|
function assertPersonalWalletInitializationOutboxIntent(intent) {
|
|
8805
|
-
|
|
9979
|
+
assertExactKeys6(intent, OUTBOX_KEYS, "Wallet initialization outbox intent");
|
|
8806
9980
|
economyAssert(
|
|
8807
9981
|
intent.schemaVersion === ECONOMY_CONTRACT_VERSION && intent.eventType === "wallet.initialized.v1",
|
|
8808
9982
|
"INVALID_CONTRACT",
|
|
@@ -8902,8 +10076,8 @@ function createPersonalWalletInitializationState(input, hash) {
|
|
|
8902
10076
|
return state;
|
|
8903
10077
|
}
|
|
8904
10078
|
function assertPersonalWalletInitializationState(state) {
|
|
8905
|
-
|
|
8906
|
-
|
|
10079
|
+
assertExactKeys6(state, STATE_KEYS, "Wallet initialization state");
|
|
10080
|
+
assertExactKeys6(
|
|
8907
10081
|
state.documentIds,
|
|
8908
10082
|
DOCUMENT_ID_KEYS,
|
|
8909
10083
|
"Wallet initialization document IDs"
|
|
@@ -8935,6 +10109,13 @@ function assertPersonalWalletInitializationState(state) {
|
|
|
8935
10109
|
}
|
|
8936
10110
|
// Annotate the CommonJS export names for ESM import in node:
|
|
8937
10111
|
0 && (module.exports = {
|
|
10112
|
+
ADMIN_TOKEN_ANOMALY_BASELINE_DAYS,
|
|
10113
|
+
ADMIN_TOKEN_DEFAULT_WINDOW_DAYS,
|
|
10114
|
+
ADMIN_TOKEN_MAXIMUM_HOURLY_WINDOW_DAYS,
|
|
10115
|
+
ADMIN_TOKEN_MAXIMUM_PAGE_SIZE,
|
|
10116
|
+
ADMIN_TOKEN_MAXIMUM_TREND_POINTS,
|
|
10117
|
+
ADMIN_TOKEN_MAXIMUM_WINDOW_DAYS,
|
|
10118
|
+
ADMIN_TOKEN_MINIMUM_COHORT_SIZE,
|
|
8938
10119
|
BASELINE_GBP_CATALOG_VERSION,
|
|
8939
10120
|
BASELINE_GBP_REFERENCE_RATE,
|
|
8940
10121
|
BASELINE_GBP_TOKEN_PACKS,
|
|
@@ -8962,6 +10143,19 @@ function assertPersonalWalletInitializationState(state) {
|
|
|
8962
10143
|
applyWalletBalanceDelta,
|
|
8963
10144
|
applyWalletLifetimeDeltas,
|
|
8964
10145
|
assertActivityEntry,
|
|
10146
|
+
assertAdminTokenActivityCursorBinding,
|
|
10147
|
+
assertAdminTokenActivityEntry,
|
|
10148
|
+
assertAdminTokenActivityPage,
|
|
10149
|
+
assertAdminTokenActivityPageForRequest,
|
|
10150
|
+
assertAdminTokenActivityPageRequest,
|
|
10151
|
+
assertAdminTokenEconomySummary,
|
|
10152
|
+
assertAdminTokenTrendRequest,
|
|
10153
|
+
assertAdminTokenTrendResult,
|
|
10154
|
+
assertAdminTokenTrendResultForRequest,
|
|
10155
|
+
assertAdminTokenWalletBalanceCursorBinding,
|
|
10156
|
+
assertAdminTokenWalletBalancePage,
|
|
10157
|
+
assertAdminTokenWalletBalancePageForRequest,
|
|
10158
|
+
assertAdminTokenWalletBalancePageRequest,
|
|
8965
10159
|
assertAuditedEconomyCommandEnvelope,
|
|
8966
10160
|
assertBalancedTransaction,
|
|
8967
10161
|
assertDeterministicWalletBalanceSummary,
|
|
@@ -9091,6 +10285,9 @@ function assertPersonalWalletInitializationState(state) {
|
|
|
9091
10285
|
canonicalTransactionPayload,
|
|
9092
10286
|
closeModuleAllowance,
|
|
9093
10287
|
convertRewardPayout,
|
|
10288
|
+
createAdminTokenAnomalyIndicator,
|
|
10289
|
+
createAdminTokenAnomalyUnavailable,
|
|
10290
|
+
createDefaultAdminTokenReportingWindow,
|
|
9094
10291
|
createEarlyBackerRetentionFromPaidLot,
|
|
9095
10292
|
createEconomyPortableCustomerReceipt,
|
|
9096
10293
|
createEconomyRecoveryAcceptanceEnvelope,
|