@metamask/ramps-controller 21.0.0 → 23.0.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.
Files changed (44) hide show
  1. package/CHANGELOG.md +42 -1
  2. package/dist/RampsController-method-action-types.d.ts +62 -1
  3. package/dist/RampsController-method-action-types.d.ts.map +1 -1
  4. package/dist/RampsController-method-action-types.js.map +1 -1
  5. package/dist/RampsController.d.ts +129 -7
  6. package/dist/RampsController.d.ts.map +1 -1
  7. package/dist/RampsController.js +392 -23
  8. package/dist/RampsController.js.map +1 -1
  9. package/dist/RampsService.d.ts +6 -0
  10. package/dist/RampsService.d.ts.map +1 -1
  11. package/dist/RampsService.js.map +1 -1
  12. package/dist/TransakService.d.ts +3 -1
  13. package/dist/TransakService.d.ts.map +1 -1
  14. package/dist/TransakService.js +10 -3
  15. package/dist/TransakService.js.map +1 -1
  16. package/dist/index.d.ts +3 -1
  17. package/dist/index.d.ts.map +1 -1
  18. package/dist/index.js +1 -0
  19. package/dist/index.js.map +1 -1
  20. package/dist/order-syncing/constants.d.ts +23 -0
  21. package/dist/order-syncing/constants.d.ts.map +1 -0
  22. package/dist/order-syncing/constants.js +23 -0
  23. package/dist/order-syncing/constants.js.map +1 -0
  24. package/dist/order-syncing/controller-integration.d.ts +91 -0
  25. package/dist/order-syncing/controller-integration.d.ts.map +1 -0
  26. package/dist/order-syncing/controller-integration.js +364 -0
  27. package/dist/order-syncing/controller-integration.js.map +1 -0
  28. package/dist/order-syncing/index.d.ts +7 -0
  29. package/dist/order-syncing/index.d.ts.map +1 -0
  30. package/dist/order-syncing/index.js +5 -0
  31. package/dist/order-syncing/index.js.map +1 -0
  32. package/dist/order-syncing/sync-utils.d.ts +9 -0
  33. package/dist/order-syncing/sync-utils.d.ts.map +1 -0
  34. package/dist/order-syncing/sync-utils.js +27 -0
  35. package/dist/order-syncing/sync-utils.js.map +1 -0
  36. package/dist/order-syncing/types.d.ts +66 -0
  37. package/dist/order-syncing/types.d.ts.map +1 -0
  38. package/dist/order-syncing/types.js +2 -0
  39. package/dist/order-syncing/types.js.map +1 -0
  40. package/dist/order-syncing/utils.d.ts +83 -0
  41. package/dist/order-syncing/utils.d.ts.map +1 -0
  42. package/dist/order-syncing/utils.js +144 -0
  43. package/dist/order-syncing/utils.js.map +1 -0
  44. package/package.json +5 -3
@@ -0,0 +1,83 @@
1
+ import type { RampsOrder } from '../RampsService.js';
2
+ import type { SyncRampsOrder, UserStorageRampsOrderEntry } from './types.js';
3
+ /**
4
+ * Converts persisted ramps timestamps to epoch milliseconds.
5
+ *
6
+ * Portfolio and older clients may persist ISO strings or numeric strings even
7
+ * though the controller's public order type uses numbers.
8
+ *
9
+ * @param value - A timestamp from a local or remote order.
10
+ * @returns Epoch milliseconds, or zero when the value is invalid.
11
+ */
12
+ export declare function normalizeCreatedAt(value: unknown): number;
13
+ /**
14
+ * Creates a unique storage key for a ramps order.
15
+ * Mirrors {@link getInternalOrderCode} without importing the controller module
16
+ * (avoids circular dependencies).
17
+ *
18
+ * Prefers a non-empty `/orders/<code>` suffix; otherwise falls back to a trimmed
19
+ * `providerOrderId`. An empty `/orders/` segment does not win over a real
20
+ * provider order id.
21
+ *
22
+ * @param order - Order fields used to derive the internal order code.
23
+ * @returns Storage entry key under the rampsOrders feature.
24
+ */
25
+ export declare function createOrderStorageKey(order: Pick<RampsOrder, 'id' | 'providerOrderId'>): string;
26
+ /**
27
+ * Whether an order has the minimum fields required for syncing.
28
+ *
29
+ * @param order - The order to validate.
30
+ * @returns True when the order can be synced.
31
+ */
32
+ export declare function isSyncableOrder(order: Pick<RampsOrder, 'id' | 'providerOrderId'>): boolean;
33
+ /**
34
+ * Strips bank-transfer / PII-heavy payment details before persisting to User
35
+ * Storage. Local controller state may still keep `paymentDetails`.
36
+ *
37
+ * @param order - Order that may include payment details.
38
+ * @returns Order body safe for remote sync payloads.
39
+ */
40
+ export declare function stripPaymentDetailsForRemoteStorage(order: RampsOrder): RampsOrder;
41
+ /**
42
+ * Maps a ramps order (with optional sync metadata) to a User Storage entry.
43
+ *
44
+ * @param order - The order to map.
45
+ * @returns A User Storage entry ready to be JSON-stringified.
46
+ */
47
+ export declare function mapRampsOrderToUserStorageEntry(order: SyncRampsOrder): UserStorageRampsOrderEntry;
48
+ /**
49
+ * Maps a User Storage entry back to a sync-aware ramps order.
50
+ *
51
+ * @param entry - The User Storage entry.
52
+ * @returns A {@link SyncRampsOrder} for merge logic.
53
+ */
54
+ export declare function mapUserStorageEntryToRampsOrder(entry: UserStorageRampsOrderEntry): SyncRampsOrder;
55
+ /**
56
+ * Strips sync metadata for equality checks and remote payload shaping.
57
+ *
58
+ * @param order - Order that may include sync metadata.
59
+ * @returns A plain {@link RampsOrder} without sync fields.
60
+ */
61
+ export declare function stripSyncMetadata(order: SyncRampsOrder): RampsOrder;
62
+ /**
63
+ * Strips remote tombstone metadata while preserving `lastUpdatedAt` so local
64
+ * controller state can participate in last-write-wins conflict resolution.
65
+ *
66
+ * @param order - Order that may include sync metadata.
67
+ * @returns Order safe to persist locally (no `deletedAt`).
68
+ */
69
+ export declare function stripDeletedAt(order: SyncRampsOrder): SyncRampsOrder;
70
+ /**
71
+ * Deep-compares two ramps orders by their syncable bodies. Sync metadata
72
+ * (`lastUpdatedAt` / `deletedAt`) and local-only `paymentDetails` are excluded:
73
+ * `paymentDetails` is never persisted remotely, so a local order that carries
74
+ * it must still compare equal to its remote copy. Otherwise such orders would
75
+ * look changed on every sync and, with local-wins-on-tie conflict resolution,
76
+ * be re-uploaded indefinitely.
77
+ *
78
+ * @param a - First order.
79
+ * @param b - Second order.
80
+ * @returns True when the syncable order payloads are equal.
81
+ */
82
+ export declare function areOrdersEqual(a: SyncRampsOrder | RampsOrder, b: SyncRampsOrder | RampsOrder): boolean;
83
+ //# sourceMappingURL=utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/order-syncing/utils.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAErD,OAAO,KAAK,EAAE,cAAc,EAAE,0BAA0B,EAAE,MAAM,YAAY,CAAC;AAE7E;;;;;;;;GAQG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAgBzD;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,qBAAqB,CACnC,KAAK,EAAE,IAAI,CAAC,UAAU,EAAE,IAAI,GAAG,iBAAiB,CAAC,GAChD,MAAM,CASR;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAC7B,KAAK,EAAE,IAAI,CAAC,UAAU,EAAE,IAAI,GAAG,iBAAiB,CAAC,GAChD,OAAO,CAET;AAED;;;;;;GAMG;AACH,wBAAgB,mCAAmC,CACjD,KAAK,EAAE,UAAU,GAChB,UAAU,CAGZ;AAED;;;;;GAKG;AACH,wBAAgB,+BAA+B,CAC7C,KAAK,EAAE,cAAc,GACpB,0BAA0B,CAa5B;AAED;;;;;GAKG;AACH,wBAAgB,+BAA+B,CAC7C,KAAK,EAAE,0BAA0B,GAChC,cAAc,CAOhB;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,cAAc,GAAG,UAAU,CAOnE;AAED;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,cAAc,GAAG,cAAc,CAGpE;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,cAAc,CAC5B,CAAC,EAAE,cAAc,GAAG,UAAU,EAC9B,CAAC,EAAE,cAAc,GAAG,UAAU,GAC7B,OAAO,CAYT"}
@@ -0,0 +1,144 @@
1
+ import deepEqual from 'fast-deep-equal';
2
+ import { USER_STORAGE_VERSION, USER_STORAGE_VERSION_KEY } from './constants.js';
3
+ /**
4
+ * Converts persisted ramps timestamps to epoch milliseconds.
5
+ *
6
+ * Portfolio and older clients may persist ISO strings or numeric strings even
7
+ * though the controller's public order type uses numbers.
8
+ *
9
+ * @param value - A timestamp from a local or remote order.
10
+ * @returns Epoch milliseconds, or zero when the value is invalid.
11
+ */
12
+ export function normalizeCreatedAt(value) {
13
+ if (typeof value === 'number') {
14
+ return Number.isFinite(value) ? value : 0;
15
+ }
16
+ if (typeof value !== 'string' || value.trim() === '') {
17
+ return 0;
18
+ }
19
+ const numericValue = Number(value);
20
+ if (Number.isFinite(numericValue)) {
21
+ return numericValue;
22
+ }
23
+ const parsedValue = Date.parse(value);
24
+ return Number.isNaN(parsedValue) ? 0 : parsedValue;
25
+ }
26
+ /**
27
+ * Creates a unique storage key for a ramps order.
28
+ * Mirrors {@link getInternalOrderCode} without importing the controller module
29
+ * (avoids circular dependencies).
30
+ *
31
+ * Prefers a non-empty `/orders/<code>` suffix; otherwise falls back to a trimmed
32
+ * `providerOrderId`. An empty `/orders/` segment does not win over a real
33
+ * provider order id.
34
+ *
35
+ * @param order - Order fields used to derive the internal order code.
36
+ * @returns Storage entry key under the rampsOrders feature.
37
+ */
38
+ export function createOrderStorageKey(order) {
39
+ const { id, providerOrderId } = order;
40
+ if (id?.includes('/orders/')) {
41
+ const code = id.split('/orders/')[1]?.trim();
42
+ if (code) {
43
+ return code;
44
+ }
45
+ }
46
+ return providerOrderId?.trim() ?? '';
47
+ }
48
+ /**
49
+ * Whether an order has the minimum fields required for syncing.
50
+ *
51
+ * @param order - The order to validate.
52
+ * @returns True when the order can be synced.
53
+ */
54
+ export function isSyncableOrder(order) {
55
+ return createOrderStorageKey(order).length > 0;
56
+ }
57
+ /**
58
+ * Strips bank-transfer / PII-heavy payment details before persisting to User
59
+ * Storage. Local controller state may still keep `paymentDetails`.
60
+ *
61
+ * @param order - Order that may include payment details.
62
+ * @returns Order body safe for remote sync payloads.
63
+ */
64
+ export function stripPaymentDetailsForRemoteStorage(order) {
65
+ const { paymentDetails: _paymentDetails, ...safeOrder } = order;
66
+ return safeOrder;
67
+ }
68
+ /**
69
+ * Maps a ramps order (with optional sync metadata) to a User Storage entry.
70
+ *
71
+ * @param order - The order to map.
72
+ * @returns A User Storage entry ready to be JSON-stringified.
73
+ */
74
+ export function mapRampsOrderToUserStorageEntry(order) {
75
+ const { lastUpdatedAt, deletedAt, ...rampsOrder } = order;
76
+ const now = Date.now();
77
+ return {
78
+ [USER_STORAGE_VERSION_KEY]: USER_STORAGE_VERSION,
79
+ o: {
80
+ ...stripPaymentDetailsForRemoteStorage(rampsOrder),
81
+ createdAt: normalizeCreatedAt(rampsOrder.createdAt),
82
+ },
83
+ lu: lastUpdatedAt ?? now,
84
+ ...(deletedAt ? { dt: deletedAt } : {}),
85
+ };
86
+ }
87
+ /**
88
+ * Maps a User Storage entry back to a sync-aware ramps order.
89
+ *
90
+ * @param entry - The User Storage entry.
91
+ * @returns A {@link SyncRampsOrder} for merge logic.
92
+ */
93
+ export function mapUserStorageEntryToRampsOrder(entry) {
94
+ return {
95
+ ...entry.o,
96
+ createdAt: normalizeCreatedAt(entry.o.createdAt),
97
+ ...(entry.lu ? { lastUpdatedAt: entry.lu } : {}),
98
+ ...(entry.dt ? { deletedAt: entry.dt } : {}),
99
+ };
100
+ }
101
+ /**
102
+ * Strips sync metadata for equality checks and remote payload shaping.
103
+ *
104
+ * @param order - Order that may include sync metadata.
105
+ * @returns A plain {@link RampsOrder} without sync fields.
106
+ */
107
+ export function stripSyncMetadata(order) {
108
+ const { lastUpdatedAt: _lastUpdatedAt, deletedAt: _deletedAt, ...rampsOrder } = order;
109
+ return rampsOrder;
110
+ }
111
+ /**
112
+ * Strips remote tombstone metadata while preserving `lastUpdatedAt` so local
113
+ * controller state can participate in last-write-wins conflict resolution.
114
+ *
115
+ * @param order - Order that may include sync metadata.
116
+ * @returns Order safe to persist locally (no `deletedAt`).
117
+ */
118
+ export function stripDeletedAt(order) {
119
+ const { deletedAt: _deletedAt, ...rampsOrder } = order;
120
+ return rampsOrder;
121
+ }
122
+ /**
123
+ * Deep-compares two ramps orders by their syncable bodies. Sync metadata
124
+ * (`lastUpdatedAt` / `deletedAt`) and local-only `paymentDetails` are excluded:
125
+ * `paymentDetails` is never persisted remotely, so a local order that carries
126
+ * it must still compare equal to its remote copy. Otherwise such orders would
127
+ * look changed on every sync and, with local-wins-on-tie conflict resolution,
128
+ * be re-uploaded indefinitely.
129
+ *
130
+ * @param a - First order.
131
+ * @param b - Second order.
132
+ * @returns True when the syncable order payloads are equal.
133
+ */
134
+ export function areOrdersEqual(a, b) {
135
+ const normalizeOrder = (order) => {
136
+ const syncableOrder = stripPaymentDetailsForRemoteStorage(stripSyncMetadata(order));
137
+ return {
138
+ ...syncableOrder,
139
+ createdAt: normalizeCreatedAt(syncableOrder.createdAt),
140
+ };
141
+ };
142
+ return deepEqual(normalizeOrder(a), normalizeOrder(b));
143
+ }
144
+ //# sourceMappingURL=utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.js","sourceRoot":"","sources":["../../src/order-syncing/utils.ts"],"names":[],"mappings":"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","sourcesContent":["import deepEqual from 'fast-deep-equal';\n\nimport type { RampsOrder } from '../RampsService.js';\nimport { USER_STORAGE_VERSION, USER_STORAGE_VERSION_KEY } from './constants.js';\nimport type { SyncRampsOrder, UserStorageRampsOrderEntry } from './types.js';\n\n/**\n * Converts persisted ramps timestamps to epoch milliseconds.\n *\n * Portfolio and older clients may persist ISO strings or numeric strings even\n * though the controller's public order type uses numbers.\n *\n * @param value - A timestamp from a local or remote order.\n * @returns Epoch milliseconds, or zero when the value is invalid.\n */\nexport function normalizeCreatedAt(value: unknown): number {\n if (typeof value === 'number') {\n return Number.isFinite(value) ? value : 0;\n }\n\n if (typeof value !== 'string' || value.trim() === '') {\n return 0;\n }\n\n const numericValue = Number(value);\n if (Number.isFinite(numericValue)) {\n return numericValue;\n }\n\n const parsedValue = Date.parse(value);\n return Number.isNaN(parsedValue) ? 0 : parsedValue;\n}\n\n/**\n * Creates a unique storage key for a ramps order.\n * Mirrors {@link getInternalOrderCode} without importing the controller module\n * (avoids circular dependencies).\n *\n * Prefers a non-empty `/orders/<code>` suffix; otherwise falls back to a trimmed\n * `providerOrderId`. An empty `/orders/` segment does not win over a real\n * provider order id.\n *\n * @param order - Order fields used to derive the internal order code.\n * @returns Storage entry key under the rampsOrders feature.\n */\nexport function createOrderStorageKey(\n order: Pick<RampsOrder, 'id' | 'providerOrderId'>,\n): string {\n const { id, providerOrderId } = order;\n if (id?.includes('/orders/')) {\n const code = id.split('/orders/')[1]?.trim();\n if (code) {\n return code;\n }\n }\n return providerOrderId?.trim() ?? '';\n}\n\n/**\n * Whether an order has the minimum fields required for syncing.\n *\n * @param order - The order to validate.\n * @returns True when the order can be synced.\n */\nexport function isSyncableOrder(\n order: Pick<RampsOrder, 'id' | 'providerOrderId'>,\n): boolean {\n return createOrderStorageKey(order).length > 0;\n}\n\n/**\n * Strips bank-transfer / PII-heavy payment details before persisting to User\n * Storage. Local controller state may still keep `paymentDetails`.\n *\n * @param order - Order that may include payment details.\n * @returns Order body safe for remote sync payloads.\n */\nexport function stripPaymentDetailsForRemoteStorage(\n order: RampsOrder,\n): RampsOrder {\n const { paymentDetails: _paymentDetails, ...safeOrder } = order;\n return safeOrder;\n}\n\n/**\n * Maps a ramps order (with optional sync metadata) to a User Storage entry.\n *\n * @param order - The order to map.\n * @returns A User Storage entry ready to be JSON-stringified.\n */\nexport function mapRampsOrderToUserStorageEntry(\n order: SyncRampsOrder,\n): UserStorageRampsOrderEntry {\n const { lastUpdatedAt, deletedAt, ...rampsOrder } = order;\n const now = Date.now();\n\n return {\n [USER_STORAGE_VERSION_KEY]: USER_STORAGE_VERSION,\n o: {\n ...stripPaymentDetailsForRemoteStorage(rampsOrder),\n createdAt: normalizeCreatedAt(rampsOrder.createdAt),\n },\n lu: lastUpdatedAt ?? now,\n ...(deletedAt ? { dt: deletedAt } : {}),\n };\n}\n\n/**\n * Maps a User Storage entry back to a sync-aware ramps order.\n *\n * @param entry - The User Storage entry.\n * @returns A {@link SyncRampsOrder} for merge logic.\n */\nexport function mapUserStorageEntryToRampsOrder(\n entry: UserStorageRampsOrderEntry,\n): SyncRampsOrder {\n return {\n ...entry.o,\n createdAt: normalizeCreatedAt(entry.o.createdAt),\n ...(entry.lu ? { lastUpdatedAt: entry.lu } : {}),\n ...(entry.dt ? { deletedAt: entry.dt } : {}),\n };\n}\n\n/**\n * Strips sync metadata for equality checks and remote payload shaping.\n *\n * @param order - Order that may include sync metadata.\n * @returns A plain {@link RampsOrder} without sync fields.\n */\nexport function stripSyncMetadata(order: SyncRampsOrder): RampsOrder {\n const {\n lastUpdatedAt: _lastUpdatedAt,\n deletedAt: _deletedAt,\n ...rampsOrder\n } = order;\n return rampsOrder;\n}\n\n/**\n * Strips remote tombstone metadata while preserving `lastUpdatedAt` so local\n * controller state can participate in last-write-wins conflict resolution.\n *\n * @param order - Order that may include sync metadata.\n * @returns Order safe to persist locally (no `deletedAt`).\n */\nexport function stripDeletedAt(order: SyncRampsOrder): SyncRampsOrder {\n const { deletedAt: _deletedAt, ...rampsOrder } = order;\n return rampsOrder;\n}\n\n/**\n * Deep-compares two ramps orders by their syncable bodies. Sync metadata\n * (`lastUpdatedAt` / `deletedAt`) and local-only `paymentDetails` are excluded:\n * `paymentDetails` is never persisted remotely, so a local order that carries\n * it must still compare equal to its remote copy. Otherwise such orders would\n * look changed on every sync and, with local-wins-on-tie conflict resolution,\n * be re-uploaded indefinitely.\n *\n * @param a - First order.\n * @param b - Second order.\n * @returns True when the syncable order payloads are equal.\n */\nexport function areOrdersEqual(\n a: SyncRampsOrder | RampsOrder,\n b: SyncRampsOrder | RampsOrder,\n): boolean {\n const normalizeOrder = (order: SyncRampsOrder | RampsOrder): RampsOrder => {\n const syncableOrder = stripPaymentDetailsForRemoteStorage(\n stripSyncMetadata(order as SyncRampsOrder),\n );\n return {\n ...syncableOrder,\n createdAt: normalizeCreatedAt(syncableOrder.createdAt),\n };\n };\n\n return deepEqual(normalizeOrder(a), normalizeOrder(b));\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@metamask/ramps-controller",
3
- "version": "21.0.0",
3
+ "version": "23.0.0",
4
4
  "description": "A controller for managing cryptocurrency on/off ramps functionality",
5
5
  "keywords": [
6
6
  "Ethereum",
@@ -54,8 +54,10 @@
54
54
  "@metamask/base-controller": "^10.0.0",
55
55
  "@metamask/controller-utils": "^13.0.0",
56
56
  "@metamask/messenger": "^3.0.0",
57
- "@metamask/profile-sync-controller": "^31.0.0",
58
- "@metamask/remote-feature-flag-controller": "^7.0.0"
57
+ "@metamask/profile-sync-controller": "^32.1.1",
58
+ "@metamask/remote-feature-flag-controller": "^7.0.0",
59
+ "bignumber.js": "^9.1.2",
60
+ "fast-deep-equal": "^3.1.3"
59
61
  },
60
62
  "devDependencies": {
61
63
  "@metamask/auto-changelog": "^6.1.0",