@boostxyz/sdk 7.1.0 → 7.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/Actions/EventAction.cjs +1 -1
- package/dist/Actions/EventAction.cjs.map +1 -1
- package/dist/Actions/EventAction.d.ts +46 -0
- package/dist/Actions/EventAction.d.ts.map +1 -1
- package/dist/Actions/EventAction.js +395 -345
- package/dist/Actions/EventAction.js.map +1 -1
- package/dist/Incentives/ERC20PeggedVariableCriteriaIncentiveV2.cjs +1 -1
- package/dist/Incentives/ERC20PeggedVariableCriteriaIncentiveV2.cjs.map +1 -1
- package/dist/Incentives/ERC20PeggedVariableCriteriaIncentiveV2.d.ts.map +1 -1
- package/dist/Incentives/ERC20PeggedVariableCriteriaIncentiveV2.js +79 -68
- package/dist/Incentives/ERC20PeggedVariableCriteriaIncentiveV2.js.map +1 -1
- package/dist/Incentives/ERC20VariableCriteriaIncentiveV2.cjs +1 -1
- package/dist/Incentives/ERC20VariableCriteriaIncentiveV2.cjs.map +1 -1
- package/dist/Incentives/ERC20VariableCriteriaIncentiveV2.d.ts.map +1 -1
- package/dist/Incentives/ERC20VariableCriteriaIncentiveV2.js +84 -73
- package/dist/Incentives/ERC20VariableCriteriaIncentiveV2.js.map +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.js +179 -175
- package/package.json +1 -1
- package/src/Actions/EventAction.test.ts +90 -0
- package/src/Actions/EventAction.ts +119 -2
- package/src/Incentives/ERC20PeggedVariableCriteriaIncentiveV2.ts +24 -5
- package/src/Incentives/ERC20VariableCriteriaIncentiveV2.ts +25 -5
|
@@ -41,6 +41,9 @@ import {
|
|
|
41
41
|
transactionSenderClaimant,
|
|
42
42
|
packFieldIndexes,
|
|
43
43
|
unpackFieldIndexes,
|
|
44
|
+
packCriteriaFieldIndexes,
|
|
45
|
+
unpackCriteriaFieldIndexes,
|
|
46
|
+
isCriteriaFieldIndexTuple,
|
|
44
47
|
decodeAndReorderLogArgs
|
|
45
48
|
} from "./EventAction";
|
|
46
49
|
import { allKnownSignatures } from "@boostxyz/test/allKnownSignatures";
|
|
@@ -1512,3 +1515,90 @@ describe('decodeAndReorderLogArgs', () => {
|
|
|
1512
1515
|
expect(result.args[3]).toBe(5284n);
|
|
1513
1516
|
});
|
|
1514
1517
|
});
|
|
1518
|
+
|
|
1519
|
+
describe("criteria field index tuple support", () => {
|
|
1520
|
+
describe("packCriteriaFieldIndexes", () => {
|
|
1521
|
+
test("packs two indices into a single value", () => {
|
|
1522
|
+
const packed = packCriteriaFieldIndexes([3, 5])
|
|
1523
|
+
expect(packed).toBeGreaterThanOrEqual(32);
|
|
1524
|
+
expect(packed).toBeLessThanOrEqual(253);
|
|
1525
|
+
});
|
|
1526
|
+
|
|
1527
|
+
test("throws error if any index exceeds the allowed range (0-13)", () => {
|
|
1528
|
+
expect(() => packCriteriaFieldIndexes([14, 5])).toThrowError(
|
|
1529
|
+
"Tuple indices must be between 0-13"
|
|
1530
|
+
);
|
|
1531
|
+
|
|
1532
|
+
expect(() => packCriteriaFieldIndexes([5, 14])).toThrowError(
|
|
1533
|
+
"Tuple indices must be between 0-13"
|
|
1534
|
+
);
|
|
1535
|
+
|
|
1536
|
+
expect(() => packCriteriaFieldIndexes([-1, 5])).toThrowError(
|
|
1537
|
+
"Tuple indices must be between 0-13"
|
|
1538
|
+
);
|
|
1539
|
+
});
|
|
1540
|
+
|
|
1541
|
+
test("different input pairs result in different packed values", () => {
|
|
1542
|
+
const packed1 = packCriteriaFieldIndexes([1, 2]);
|
|
1543
|
+
const packed2 = packCriteriaFieldIndexes([2, 1]);
|
|
1544
|
+
const packed3 = packCriteriaFieldIndexes([1, 3]);
|
|
1545
|
+
|
|
1546
|
+
expect(packed1).not.toBe(packed2);
|
|
1547
|
+
expect(packed1).not.toBe(packed3);
|
|
1548
|
+
expect(packed2).not.toBe(packed3);
|
|
1549
|
+
});
|
|
1550
|
+
});
|
|
1551
|
+
|
|
1552
|
+
describe("unpackCriteriaFieldIndexes", () => {
|
|
1553
|
+
test("unpacks tuple index values (>= 32) correctly", () => {
|
|
1554
|
+
const packed = packCriteriaFieldIndexes([4, 7]);
|
|
1555
|
+
|
|
1556
|
+
const result = unpackCriteriaFieldIndexes(packed);
|
|
1557
|
+
expect(result.length).toBe(2);
|
|
1558
|
+
expect(result).toEqual([4, 7]);
|
|
1559
|
+
});
|
|
1560
|
+
|
|
1561
|
+
test("throws error if packed value is out of valid range", () => {
|
|
1562
|
+
expect(() => unpackCriteriaFieldIndexes(15)).toThrowError(
|
|
1563
|
+
"Field index must be between 32-253"
|
|
1564
|
+
);
|
|
1565
|
+
|
|
1566
|
+
expect(() => unpackCriteriaFieldIndexes(254)).toThrowError(
|
|
1567
|
+
"Field index must be between 32-253"
|
|
1568
|
+
);
|
|
1569
|
+
|
|
1570
|
+
expect(() => unpackCriteriaFieldIndexes(-1)).toThrowError(
|
|
1571
|
+
"Field index must be between 32-253"
|
|
1572
|
+
);
|
|
1573
|
+
});
|
|
1574
|
+
});
|
|
1575
|
+
|
|
1576
|
+
describe("isCriteriaFieldIndexTuple", () => {
|
|
1577
|
+
test("correctly identifies tuple indices vs simple indices", () => {
|
|
1578
|
+
// Test with simple index (< 32)
|
|
1579
|
+
expect(isCriteriaFieldIndexTuple(15)).toBe(false);
|
|
1580
|
+
|
|
1581
|
+
// Test with tuple index (>= 32)
|
|
1582
|
+
const packed = packCriteriaFieldIndexes([2, 3]);
|
|
1583
|
+
expect(isCriteriaFieldIndexTuple(packed)).toBe(true);
|
|
1584
|
+
|
|
1585
|
+
// Test edge cases
|
|
1586
|
+
expect(isCriteriaFieldIndexTuple(0)).toBe(false);
|
|
1587
|
+
expect(isCriteriaFieldIndexTuple(31)).toBe(false);
|
|
1588
|
+
expect(isCriteriaFieldIndexTuple(32)).toBe(true);
|
|
1589
|
+
});
|
|
1590
|
+
});
|
|
1591
|
+
|
|
1592
|
+
describe("criteria field index functions in practice", () => {
|
|
1593
|
+
test("round-trip packing and unpacking preserves the original values", () => {
|
|
1594
|
+
for (let i = 0; i <= 13; i++) {
|
|
1595
|
+
for (let j = 0; j <= 13; j++) {
|
|
1596
|
+
const original: [number, number] = [i, j];
|
|
1597
|
+
const packed = packCriteriaFieldIndexes(original);
|
|
1598
|
+
const unpacked = unpackCriteriaFieldIndexes(packed);
|
|
1599
|
+
expect(unpacked).toEqual(original);
|
|
1600
|
+
}
|
|
1601
|
+
}
|
|
1602
|
+
});
|
|
1603
|
+
});
|
|
1604
|
+
});
|
|
@@ -584,7 +584,7 @@ export class EventAction extends DeployableTarget<
|
|
|
584
584
|
claimant,
|
|
585
585
|
log,
|
|
586
586
|
);
|
|
587
|
-
if (addressCandidate)
|
|
587
|
+
if (addressCandidate) return addressCandidate;
|
|
588
588
|
}
|
|
589
589
|
return address;
|
|
590
590
|
}
|
|
@@ -611,7 +611,7 @@ export class EventAction extends DeployableTarget<
|
|
|
611
611
|
for (let log of decodedLogs) {
|
|
612
612
|
if (!isAddressEqual(log.address, claimant.targetContract)) continue;
|
|
613
613
|
let addressCandidate = this.validateClaimantAgainstArgs(claimant, log);
|
|
614
|
-
if (addressCandidate)
|
|
614
|
+
if (addressCandidate) return addressCandidate;
|
|
615
615
|
}
|
|
616
616
|
return address;
|
|
617
617
|
}
|
|
@@ -1781,3 +1781,120 @@ export function decodeAndReorderLogArgs(event: AbiEvent, log: Log) {
|
|
|
1781
1781
|
args: reorderedArgs,
|
|
1782
1782
|
} as EventLog;
|
|
1783
1783
|
}
|
|
1784
|
+
|
|
1785
|
+
/**
|
|
1786
|
+
* IMPORTANT: For variable incentive criteria use only.
|
|
1787
|
+
* Do NOT use for action steps - use {@link packFieldIndexes} instead.
|
|
1788
|
+
*
|
|
1789
|
+
* Packs two field indices into a single uint8 value for criteria tuple access.
|
|
1790
|
+
* Both indices must be between 0-13 to fit in the packed format.
|
|
1791
|
+
*
|
|
1792
|
+
* Uses an offset of 32 to avoid collision with normal field indices (which are 0-31),
|
|
1793
|
+
* allowing the system to distinguish between direct field access and tuple access.
|
|
1794
|
+
*
|
|
1795
|
+
* @export
|
|
1796
|
+
* @param {[number, number]} param0 - A tuple of [firstIndex, secondIndex]
|
|
1797
|
+
* @returns {number} - Packed uint8 value with base offset of 32
|
|
1798
|
+
* @throws {InvalidTupleEncodingError} - If either index is outside the valid range (0-13)
|
|
1799
|
+
*/
|
|
1800
|
+
export function packCriteriaFieldIndexes([firstIndex, secondIndex]: [
|
|
1801
|
+
number,
|
|
1802
|
+
number,
|
|
1803
|
+
]): number {
|
|
1804
|
+
if (
|
|
1805
|
+
firstIndex < 0 ||
|
|
1806
|
+
firstIndex > 13 ||
|
|
1807
|
+
secondIndex < 0 ||
|
|
1808
|
+
secondIndex > 13
|
|
1809
|
+
) {
|
|
1810
|
+
throw new InvalidTupleEncodingError(
|
|
1811
|
+
`Tuple indices must be between 0-13, got: [${firstIndex}, ${secondIndex}]`,
|
|
1812
|
+
);
|
|
1813
|
+
}
|
|
1814
|
+
return 32 + (firstIndex << 4) + secondIndex;
|
|
1815
|
+
}
|
|
1816
|
+
|
|
1817
|
+
/**
|
|
1818
|
+
* Unpacks a uint8 packed index value into an array of indices.
|
|
1819
|
+
*
|
|
1820
|
+
* @export
|
|
1821
|
+
* @param {number} packed - Packed index value
|
|
1822
|
+
* @returns {[number, number]} - [firstIndex, secondIndex]
|
|
1823
|
+
*/
|
|
1824
|
+
export function unpackCriteriaFieldIndexes(packed: number): [number, number] {
|
|
1825
|
+
if (packed < 32 || packed > 253) {
|
|
1826
|
+
throw new InvalidTupleEncodingError(
|
|
1827
|
+
`Field index must be between 32-253, got: ${packed}`,
|
|
1828
|
+
);
|
|
1829
|
+
}
|
|
1830
|
+
|
|
1831
|
+
const tupleValue = packed - 32;
|
|
1832
|
+
const firstIndex = (tupleValue >> 4) & 0xf;
|
|
1833
|
+
const secondIndex = tupleValue & 0xf;
|
|
1834
|
+
return [firstIndex, secondIndex];
|
|
1835
|
+
}
|
|
1836
|
+
|
|
1837
|
+
/**
|
|
1838
|
+
* Determines if a fieldIndex represents a tuple index (value >= 32) or a normal field index.
|
|
1839
|
+
*
|
|
1840
|
+
* @export
|
|
1841
|
+
* @param {number} fieldIndex - The field index to check
|
|
1842
|
+
* @returns {boolean} - True if it's a tuple index, false if it's a normal field index
|
|
1843
|
+
*/
|
|
1844
|
+
export function isCriteriaFieldIndexTuple(fieldIndex: number): boolean {
|
|
1845
|
+
return fieldIndex >= 32;
|
|
1846
|
+
}
|
|
1847
|
+
|
|
1848
|
+
/**
|
|
1849
|
+
* Extracts a scalar value from a tuple within event or function arguments.
|
|
1850
|
+
* This is used for incentive criteria when determining reward amounts.
|
|
1851
|
+
*
|
|
1852
|
+
* @export
|
|
1853
|
+
* @param {unknown[]} args - The decoded arguments from an event or function call
|
|
1854
|
+
* @param {number} fieldIndex - The tuple-encoded index
|
|
1855
|
+
* @returns {bigint} The extracted scalar value as a bigint
|
|
1856
|
+
* @throws {DecodedArgsError} If arguments are missing or cannot be converted to bigint
|
|
1857
|
+
*/
|
|
1858
|
+
export function getScalarValueFromTuple(
|
|
1859
|
+
args: unknown[],
|
|
1860
|
+
fieldIndex: number,
|
|
1861
|
+
): bigint {
|
|
1862
|
+
if (!isCriteriaFieldIndexTuple(fieldIndex)) {
|
|
1863
|
+
throw new DecodedArgsError(
|
|
1864
|
+
`Field index ${fieldIndex} is invalid. Expected index >= 32`,
|
|
1865
|
+
);
|
|
1866
|
+
}
|
|
1867
|
+
|
|
1868
|
+
const [index0, index1] = unpackCriteriaFieldIndexes(fieldIndex);
|
|
1869
|
+
|
|
1870
|
+
if (index0 === undefined || index1 === undefined) {
|
|
1871
|
+
throw new DecodedArgsError(
|
|
1872
|
+
`Failed to unpack field indexes from ${fieldIndex}`,
|
|
1873
|
+
);
|
|
1874
|
+
}
|
|
1875
|
+
|
|
1876
|
+
if (!args || args.length <= index0) {
|
|
1877
|
+
throw new DecodedArgsError(`Decoded args missing item at index ${index0}`);
|
|
1878
|
+
}
|
|
1879
|
+
|
|
1880
|
+
const tuple = args[index0];
|
|
1881
|
+
if (!tuple || !Array.isArray(tuple)) {
|
|
1882
|
+
throw new DecodedArgsError(
|
|
1883
|
+
`Expected array at index ${index0}, but got ${typeof tuple}`,
|
|
1884
|
+
);
|
|
1885
|
+
}
|
|
1886
|
+
if (tuple.length <= index1) {
|
|
1887
|
+
throw new DecodedArgsError(
|
|
1888
|
+
`index ${index1} is out of bounds. tuple length is ${tuple.length}`,
|
|
1889
|
+
);
|
|
1890
|
+
}
|
|
1891
|
+
|
|
1892
|
+
const scalarValue = tuple[index1] as unknown;
|
|
1893
|
+
if (typeof scalarValue !== 'bigint') {
|
|
1894
|
+
throw new DecodedArgsError(
|
|
1895
|
+
`Expected bigint at tuple index ${index1}, but got ${typeof scalarValue}`,
|
|
1896
|
+
);
|
|
1897
|
+
}
|
|
1898
|
+
|
|
1899
|
+
return scalarValue;
|
|
1900
|
+
}
|
|
@@ -35,7 +35,11 @@ import {
|
|
|
35
35
|
zeroHash,
|
|
36
36
|
} from 'viem';
|
|
37
37
|
import { ERC20PeggedVariableCriteriaIncentiveV2 as ERC20PeggedVariableCriteriaIncentiveV2Bases } from '../../dist/deployments.json';
|
|
38
|
-
import {
|
|
38
|
+
import {
|
|
39
|
+
SignatureType,
|
|
40
|
+
getScalarValueFromTuple,
|
|
41
|
+
isCriteriaFieldIndexTuple,
|
|
42
|
+
} from '../Actions/EventAction';
|
|
39
43
|
import type {
|
|
40
44
|
DeployableOptions,
|
|
41
45
|
GenericDeployableParams,
|
|
@@ -257,7 +261,6 @@ export class ERC20PeggedVariableCriteriaIncentiveV2 extends DeployableTarget<
|
|
|
257
261
|
|
|
258
262
|
// Decode the event log
|
|
259
263
|
try {
|
|
260
|
-
// Decode function data
|
|
261
264
|
const eventAbi = knownSignatures[criteria.signature] as AbiEvent;
|
|
262
265
|
const decodedEvents = parseEventLogs({
|
|
263
266
|
abi: [eventAbi],
|
|
@@ -268,10 +271,18 @@ export class ERC20PeggedVariableCriteriaIncentiveV2 extends DeployableTarget<
|
|
|
268
271
|
`No logs found for event signature ${criteria.signature}`,
|
|
269
272
|
);
|
|
270
273
|
}
|
|
271
|
-
const scalarValue = (decodedEvents[0]?.args as string[])[
|
|
272
|
-
criteria.fieldIndex
|
|
273
|
-
];
|
|
274
274
|
|
|
275
|
+
if (isCriteriaFieldIndexTuple(criteria.fieldIndex)) {
|
|
276
|
+
return getScalarValueFromTuple(
|
|
277
|
+
decodedEvents[0]?.args as unknown[],
|
|
278
|
+
criteria.fieldIndex,
|
|
279
|
+
);
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
const scalarValue =
|
|
283
|
+
decodedEvents[0] && decodedEvents[0].args
|
|
284
|
+
? (decodedEvents[0].args as string[])[criteria.fieldIndex]
|
|
285
|
+
: undefined;
|
|
275
286
|
if (scalarValue === undefined) {
|
|
276
287
|
throw new DecodedArgsError(
|
|
277
288
|
`Decoded argument at index ${criteria.fieldIndex} is undefined`,
|
|
@@ -296,6 +307,14 @@ export class ERC20PeggedVariableCriteriaIncentiveV2 extends DeployableTarget<
|
|
|
296
307
|
abi: [func],
|
|
297
308
|
data: transaction.input,
|
|
298
309
|
});
|
|
310
|
+
|
|
311
|
+
if (isCriteriaFieldIndexTuple(criteria.fieldIndex)) {
|
|
312
|
+
return getScalarValueFromTuple(
|
|
313
|
+
decodedFunction.args as unknown[],
|
|
314
|
+
criteria.fieldIndex,
|
|
315
|
+
);
|
|
316
|
+
}
|
|
317
|
+
|
|
299
318
|
const scalarValue = decodedFunction.args[criteria.fieldIndex] as string;
|
|
300
319
|
if (scalarValue === undefined || scalarValue === null) {
|
|
301
320
|
throw new DecodedArgsError(
|
|
@@ -19,7 +19,12 @@ import {
|
|
|
19
19
|
zeroHash,
|
|
20
20
|
} from 'viem';
|
|
21
21
|
import { ERC20VariableCriteriaIncentiveV2 as ERC20VariableCriteriaIncentiveV2Bases } from '../../dist/deployments.json';
|
|
22
|
-
import {
|
|
22
|
+
import {
|
|
23
|
+
SignatureType,
|
|
24
|
+
ValueType,
|
|
25
|
+
getScalarValueFromTuple,
|
|
26
|
+
isCriteriaFieldIndexTuple,
|
|
27
|
+
} from '../Actions/EventAction';
|
|
23
28
|
import type {
|
|
24
29
|
DeployableOptions,
|
|
25
30
|
GenericDeployableParams,
|
|
@@ -268,7 +273,6 @@ export class ERC20VariableCriteriaIncentiveV2 extends ERC20VariableIncentive<
|
|
|
268
273
|
|
|
269
274
|
// Decode the event log
|
|
270
275
|
try {
|
|
271
|
-
// Decode function data
|
|
272
276
|
const eventAbi = knownSignatures[criteria.signature] as AbiEvent;
|
|
273
277
|
const decodedEvents = parseEventLogs({
|
|
274
278
|
abi: [eventAbi],
|
|
@@ -279,10 +283,18 @@ export class ERC20VariableCriteriaIncentiveV2 extends ERC20VariableIncentive<
|
|
|
279
283
|
`No logs found for event signature ${criteria.signature}`,
|
|
280
284
|
);
|
|
281
285
|
}
|
|
282
|
-
const scalarValue = (decodedEvents[0]?.args as string[])[
|
|
283
|
-
criteria.fieldIndex
|
|
284
|
-
];
|
|
285
286
|
|
|
287
|
+
if (isCriteriaFieldIndexTuple(criteria.fieldIndex)) {
|
|
288
|
+
return getScalarValueFromTuple(
|
|
289
|
+
decodedEvents[0]?.args as unknown[],
|
|
290
|
+
criteria.fieldIndex,
|
|
291
|
+
);
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
const scalarValue =
|
|
295
|
+
decodedEvents[0] && decodedEvents[0].args
|
|
296
|
+
? (decodedEvents[0].args as string[])[criteria.fieldIndex]
|
|
297
|
+
: undefined;
|
|
286
298
|
if (scalarValue === undefined) {
|
|
287
299
|
throw new DecodedArgsError(
|
|
288
300
|
`Decoded argument at index ${criteria.fieldIndex} is undefined`,
|
|
@@ -307,6 +319,14 @@ export class ERC20VariableCriteriaIncentiveV2 extends ERC20VariableIncentive<
|
|
|
307
319
|
abi: [func],
|
|
308
320
|
data: transaction.input,
|
|
309
321
|
});
|
|
322
|
+
|
|
323
|
+
if (isCriteriaFieldIndexTuple(criteria.fieldIndex)) {
|
|
324
|
+
return getScalarValueFromTuple(
|
|
325
|
+
decodedFunction.args as unknown[],
|
|
326
|
+
criteria.fieldIndex,
|
|
327
|
+
);
|
|
328
|
+
}
|
|
329
|
+
|
|
310
330
|
const scalarValue = decodedFunction.args[criteria.fieldIndex] as string;
|
|
311
331
|
if (scalarValue === undefined || scalarValue === null) {
|
|
312
332
|
throw new DecodedArgsError(
|