@boostxyz/sdk 0.0.0-alpha.3 → 0.0.0-alpha.6
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/Action.cjs +2 -1
- package/dist/Actions/Action.cjs.map +1 -0
- package/dist/Actions/Action.d.ts +1 -1
- package/dist/Actions/Action.d.ts.map +1 -1
- package/dist/Actions/Action.js +15 -13
- package/dist/Actions/Action.js.map +1 -0
- package/dist/Actions/EventAction.cjs +1 -0
- package/dist/Actions/EventAction.cjs.map +1 -0
- package/dist/Actions/EventAction.js +1 -0
- package/dist/Actions/EventAction.js.map +1 -0
- package/dist/AllowLists/AllowList.cjs +2 -1
- package/dist/AllowLists/AllowList.cjs.map +1 -0
- package/dist/AllowLists/AllowList.d.ts +1 -2
- package/dist/AllowLists/AllowList.d.ts.map +1 -1
- package/dist/AllowLists/AllowList.js +16 -14
- package/dist/AllowLists/AllowList.js.map +1 -0
- package/dist/AllowLists/SimpleAllowList.cjs +1 -0
- package/dist/AllowLists/SimpleAllowList.cjs.map +1 -0
- package/dist/AllowLists/SimpleAllowList.js +1 -0
- package/dist/AllowLists/SimpleAllowList.js.map +1 -0
- package/dist/AllowLists/SimpleDenyList.cjs +1 -0
- package/dist/AllowLists/SimpleDenyList.cjs.map +1 -0
- package/dist/AllowLists/SimpleDenyList.js +1 -0
- package/dist/AllowLists/SimpleDenyList.js.map +1 -0
- package/dist/Auth/Auth.cjs +1 -0
- package/dist/Auth/Auth.cjs.map +1 -0
- package/dist/Auth/Auth.js +1 -0
- package/dist/Auth/Auth.js.map +1 -0
- package/dist/Auth/PassthroughAuth.cjs +1 -0
- package/dist/Auth/PassthroughAuth.cjs.map +1 -0
- package/dist/Auth/PassthroughAuth.js +1 -0
- package/dist/Auth/PassthroughAuth.js.map +1 -0
- package/dist/Boost.cjs +1 -0
- package/dist/Boost.cjs.map +1 -0
- package/dist/Boost.js +1 -0
- package/dist/Boost.js.map +1 -0
- package/dist/BoostCore.cjs +1 -0
- package/dist/BoostCore.cjs.map +1 -0
- package/dist/BoostCore.js +1 -0
- package/dist/BoostCore.js.map +1 -0
- package/dist/BoostRegistry.cjs +1 -0
- package/dist/BoostRegistry.cjs.map +1 -0
- package/dist/BoostRegistry.js +1 -0
- package/dist/BoostRegistry.js.map +1 -0
- package/dist/Budgets/Budget.cjs +2 -1
- package/dist/Budgets/Budget.cjs.map +1 -0
- package/dist/Budgets/Budget.d.ts +1 -1
- package/dist/Budgets/Budget.d.ts.map +1 -1
- package/dist/Budgets/Budget.js +14 -12
- package/dist/Budgets/Budget.js.map +1 -0
- package/dist/Budgets/ManagedBudget.cjs +1 -0
- package/dist/Budgets/ManagedBudget.cjs.map +1 -0
- package/dist/Budgets/ManagedBudget.js +1 -0
- package/dist/Budgets/ManagedBudget.js.map +1 -0
- package/dist/Deployable/Contract.cjs +1 -0
- package/dist/Deployable/Contract.cjs.map +1 -0
- package/dist/Deployable/Contract.js +1 -0
- package/dist/Deployable/Contract.js.map +1 -0
- package/dist/Deployable/Deployable.cjs +1 -0
- package/dist/Deployable/Deployable.cjs.map +1 -0
- package/dist/Deployable/Deployable.js +1 -0
- package/dist/Deployable/Deployable.js.map +1 -0
- package/dist/Deployable/DeployableTarget.cjs +1 -0
- package/dist/Deployable/DeployableTarget.cjs.map +1 -0
- package/dist/Deployable/DeployableTarget.js +1 -0
- package/dist/Deployable/DeployableTarget.js.map +1 -0
- package/dist/Incentives/AllowListIncentive.cjs +1 -0
- package/dist/Incentives/AllowListIncentive.cjs.map +1 -0
- package/dist/Incentives/AllowListIncentive.js +1 -0
- package/dist/Incentives/AllowListIncentive.js.map +1 -0
- package/dist/Incentives/CGDAIncentive.cjs +1 -0
- package/dist/Incentives/CGDAIncentive.cjs.map +1 -0
- package/dist/Incentives/CGDAIncentive.js +1 -0
- package/dist/Incentives/CGDAIncentive.js.map +1 -0
- package/dist/Incentives/ERC20Incentive.cjs +1 -0
- package/dist/Incentives/ERC20Incentive.cjs.map +1 -0
- package/dist/Incentives/ERC20Incentive.js +1 -0
- package/dist/Incentives/ERC20Incentive.js.map +1 -0
- package/dist/Incentives/Incentive.cjs +2 -1
- package/dist/Incentives/Incentive.cjs.map +1 -0
- package/dist/Incentives/Incentive.d.ts +1 -4
- package/dist/Incentives/Incentive.d.ts.map +1 -1
- package/dist/Incentives/Incentive.js +39 -36
- package/dist/Incentives/Incentive.js.map +1 -0
- package/dist/Incentives/PointsIncentive.cjs +1 -0
- package/dist/Incentives/PointsIncentive.cjs.map +1 -0
- package/dist/Incentives/PointsIncentive.js +1 -0
- package/dist/Incentives/PointsIncentive.js.map +1 -0
- package/dist/Validators/SignerValidator.cjs +1 -0
- package/dist/Validators/SignerValidator.cjs.map +1 -0
- package/dist/Validators/SignerValidator.js +1 -0
- package/dist/Validators/SignerValidator.js.map +1 -0
- package/dist/Validators/Validator.cjs +2 -1
- package/dist/Validators/Validator.cjs.map +1 -0
- package/dist/Validators/Validator.d.ts +1 -1
- package/dist/Validators/Validator.d.ts.map +1 -1
- package/dist/Validators/Validator.js +9 -7
- package/dist/Validators/Validator.js.map +1 -0
- package/dist/componentInterfaces-CKCBwG16.cjs +2 -0
- package/dist/componentInterfaces-CKCBwG16.cjs.map +1 -0
- package/dist/componentInterfaces-DYkaxBda.js +13 -0
- package/dist/componentInterfaces-DYkaxBda.js.map +1 -0
- package/dist/errors.cjs +1 -0
- package/dist/errors.cjs.map +1 -0
- package/dist/errors.js +1 -0
- package/dist/errors.js.map +1 -0
- package/dist/generated-Cd-Fe7W7.cjs +1 -0
- package/dist/generated-Cd-Fe7W7.cjs.map +1 -0
- package/dist/generated-DGpIVcv5.js +1 -0
- package/dist/generated-DGpIVcv5.js.map +1 -0
- package/dist/index.cjs +1 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -0
- package/dist/utils.cjs +1 -0
- package/dist/utils.cjs.map +1 -0
- package/dist/utils.d.ts +1 -1
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +1 -0
- package/dist/utils.js.map +1 -0
- package/package.json +5 -3
- package/src/Actions/Action.test.ts +77 -0
- package/src/Actions/Action.ts +61 -0
- package/src/Actions/ContractAction.test.ts +199 -0
- package/src/Actions/ContractAction.ts +238 -0
- package/src/Actions/ERC721MintAction.test.ts +112 -0
- package/src/Actions/ERC721MintAction.ts +238 -0
- package/src/Actions/EventAction.test.ts +182 -0
- package/src/Actions/EventAction.ts +382 -0
- package/src/AllowLists/AllowList.test.ts +64 -0
- package/src/AllowLists/AllowList.ts +60 -0
- package/src/AllowLists/SimpleAllowList.test.ts +52 -0
- package/src/AllowLists/SimpleAllowList.ts +240 -0
- package/src/AllowLists/SimpleDenyList.test.ts +52 -0
- package/src/AllowLists/SimpleDenyList.ts +289 -0
- package/src/Auth/Auth.ts +11 -0
- package/src/Auth/PassthroughAuth.test.ts +12 -0
- package/src/Auth/PassthroughAuth.ts +80 -0
- package/src/Boost.ts +155 -0
- package/src/BoostCore.test.ts +846 -0
- package/src/BoostCore.ts +1192 -0
- package/src/BoostRegistry.ts +449 -0
- package/src/Budgets/Budget.test.ts +27 -0
- package/src/Budgets/Budget.ts +61 -0
- package/src/Budgets/ManagedBudget.test.ts +154 -0
- package/src/Budgets/ManagedBudget.ts +743 -0
- package/src/Budgets/SimpleBudget.test.ts +152 -0
- package/src/Budgets/SimpleBudget.ts +521 -0
- package/src/Budgets/VestingBudget.test.ts +123 -0
- package/src/Budgets/VestingBudget.ts +532 -0
- package/src/Deployable/Contract.ts +229 -0
- package/src/Deployable/Deployable.ts +244 -0
- package/src/Deployable/DeployableTarget.ts +210 -0
- package/src/Incentives/AllowListIncentive.test.ts +146 -0
- package/src/Incentives/AllowListIncentive.ts +290 -0
- package/src/Incentives/CGDAIncentive.test.ts +136 -0
- package/src/Incentives/CGDAIncentive.ts +364 -0
- package/src/Incentives/ERC1155Incentive.test.ts +98 -0
- package/src/Incentives/ERC1155Incentive.ts +384 -0
- package/src/Incentives/ERC20Incentive.test.ts +141 -0
- package/src/Incentives/ERC20Incentive.ts +417 -0
- package/src/Incentives/ERC20VariableIncentive.test.ts +156 -0
- package/src/Incentives/ERC20VariableIncentive.ts +368 -0
- package/src/Incentives/Incentive.test.ts +92 -0
- package/src/Incentives/Incentive.ts +85 -0
- package/src/Incentives/PointsIncentive.test.ts +142 -0
- package/src/Incentives/PointsIncentive.ts +303 -0
- package/src/Validators/SignerValidator.test.ts +163 -0
- package/src/Validators/SignerValidator.ts +272 -0
- package/src/Validators/Validator.test.ts +21 -0
- package/src/Validators/Validator.ts +55 -0
- package/src/errors.ts +524 -0
- package/src/index.test.ts +40 -0
- package/src/index.ts +50 -0
- package/src/utils.test.ts +44 -0
- package/src/utils.ts +2247 -0
package/package.json
CHANGED
|
@@ -1,14 +1,16 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@boostxyz/sdk",
|
|
3
|
-
"version": "0.0.0-alpha.
|
|
3
|
+
"version": "0.0.0-alpha.6",
|
|
4
4
|
"license": "GPL-3.0-or-later",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"files": [
|
|
7
|
-
"dist"
|
|
7
|
+
"dist",
|
|
8
|
+
"src"
|
|
8
9
|
],
|
|
9
10
|
"repository": "https://github.com/rabbitholegg/boost-protocol",
|
|
10
11
|
"author": "Boost Team<boost-team@boost.xyz>",
|
|
11
12
|
"access": "public",
|
|
13
|
+
"private": false,
|
|
12
14
|
"browserslist": [
|
|
13
15
|
"node >=14",
|
|
14
16
|
"edge >=88",
|
|
@@ -177,7 +179,7 @@
|
|
|
177
179
|
"@boostxyz/signatures": "0.0.0-alpha.0"
|
|
178
180
|
},
|
|
179
181
|
"optionalDependencies": {
|
|
180
|
-
"@boostxyz/evm": "0.0.0-alpha.
|
|
182
|
+
"@boostxyz/evm": "0.0.0-alpha.1"
|
|
181
183
|
},
|
|
182
184
|
"peerDependencies": {
|
|
183
185
|
"@wagmi/core": "2",
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { selectors } from '@boostxyz/signatures/events';
|
|
2
|
+
import { loadFixture } from '@nomicfoundation/hardhat-toolbox-viem/network-helpers';
|
|
3
|
+
import type { Hex } from 'viem';
|
|
4
|
+
import { beforeAll, beforeEach, describe, expect, test } from 'vitest';
|
|
5
|
+
import type { MockERC721 } from '../../test/MockERC721';
|
|
6
|
+
import { accounts } from '../../test/accounts';
|
|
7
|
+
import {
|
|
8
|
+
type Fixtures,
|
|
9
|
+
defaultOptions,
|
|
10
|
+
deployFixtures,
|
|
11
|
+
fundErc721,
|
|
12
|
+
} from '../../test/helpers';
|
|
13
|
+
import {
|
|
14
|
+
type EventActionPayloadSimple,
|
|
15
|
+
FilterType,
|
|
16
|
+
PrimitiveType,
|
|
17
|
+
SignatureType,
|
|
18
|
+
} from '../utils';
|
|
19
|
+
import { EventAction, actionFromAddress } from './Action';
|
|
20
|
+
|
|
21
|
+
let fixtures: Fixtures, erc721: MockERC721;
|
|
22
|
+
|
|
23
|
+
export function basicErc721TransferAction(
|
|
24
|
+
erc721: MockERC721,
|
|
25
|
+
): EventActionPayloadSimple {
|
|
26
|
+
return {
|
|
27
|
+
actionClaimant: {
|
|
28
|
+
signatureType: SignatureType.EVENT,
|
|
29
|
+
signature: selectors['Transfer(address,address,uint256)'] as Hex,
|
|
30
|
+
fieldIndex: 2,
|
|
31
|
+
targetContract: erc721.assertValidAddress(),
|
|
32
|
+
},
|
|
33
|
+
actionSteps: [
|
|
34
|
+
{
|
|
35
|
+
signature: selectors['Transfer(address,address,uint256)'] as Hex,
|
|
36
|
+
signatureType: SignatureType.EVENT,
|
|
37
|
+
actionType: 0,
|
|
38
|
+
targetContract: erc721.assertValidAddress(),
|
|
39
|
+
actionParameter: {
|
|
40
|
+
filterType: FilterType.EQUAL,
|
|
41
|
+
fieldType: PrimitiveType.ADDRESS,
|
|
42
|
+
fieldIndex: 2,
|
|
43
|
+
filterData: accounts.at(1)!.account,
|
|
44
|
+
},
|
|
45
|
+
},
|
|
46
|
+
],
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export function cloneEventAction(fixtures: Fixtures, erc721: MockERC721) {
|
|
51
|
+
return function cloneEventAction() {
|
|
52
|
+
return fixtures.registry.clone(
|
|
53
|
+
crypto.randomUUID(),
|
|
54
|
+
new fixtures.bases.EventAction(
|
|
55
|
+
defaultOptions,
|
|
56
|
+
basicErc721TransferAction(erc721),
|
|
57
|
+
),
|
|
58
|
+
);
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
beforeAll(async () => {
|
|
63
|
+
fixtures = await loadFixture(deployFixtures);
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
describe('Action', () => {
|
|
67
|
+
beforeEach(async () => {
|
|
68
|
+
erc721 = await loadFixture(fundErc721(defaultOptions));
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
test('can automatically instantiate EventAction given an address', async () => {
|
|
72
|
+
const _action = await loadFixture(cloneEventAction(fixtures, erc721));
|
|
73
|
+
expect(
|
|
74
|
+
await actionFromAddress(defaultOptions, _action.assertValidAddress()),
|
|
75
|
+
).toBeInstanceOf(EventAction);
|
|
76
|
+
});
|
|
77
|
+
});
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { aActionAbi } from '@boostxyz/evm';
|
|
2
|
+
import { AEventAction } from '@boostxyz/evm/deploys/componentInterfaces.json';
|
|
3
|
+
import { readContract } from '@wagmi/core';
|
|
4
|
+
import type { Address, Hex } from 'viem';
|
|
5
|
+
import type { DeployableOptions } from '../Deployable/Deployable';
|
|
6
|
+
import { InvalidComponentInterfaceError } from '../errors';
|
|
7
|
+
import { EventAction } from './EventAction';
|
|
8
|
+
|
|
9
|
+
export {
|
|
10
|
+
// ContractAction,
|
|
11
|
+
// ERC721MintAction,
|
|
12
|
+
EventAction,
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* A union type representing all valid protocol Action implementations
|
|
17
|
+
*
|
|
18
|
+
* @export
|
|
19
|
+
* @typedef {Action}
|
|
20
|
+
*/
|
|
21
|
+
export type Action = EventAction; // | ContractAction | ERC721MintAction
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* A map of Action component interfaces to their constructors.
|
|
25
|
+
*
|
|
26
|
+
* @type {{ "0x7687b0ed": EventAction; }}
|
|
27
|
+
*/
|
|
28
|
+
export const ActionByComponentInterface = {
|
|
29
|
+
// ['0x6c3129aa']: ContractAction,
|
|
30
|
+
// ['0x97e083eb']: ERC721MintAction,
|
|
31
|
+
[AEventAction as Hex]: EventAction,
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* A function that will read a contract's component interface using `getComponentInterface` and return the correct instantiated instance.
|
|
36
|
+
*
|
|
37
|
+
* @export
|
|
38
|
+
* @async
|
|
39
|
+
* @param {DeployableOptions} options
|
|
40
|
+
* @param {Address} address
|
|
41
|
+
* @returns {Promise<EventAction>}
|
|
42
|
+
* @throws {@link InvalidComponentInterfaceError}
|
|
43
|
+
*/
|
|
44
|
+
export async function actionFromAddress(
|
|
45
|
+
options: DeployableOptions,
|
|
46
|
+
address: Address,
|
|
47
|
+
) {
|
|
48
|
+
const interfaceId = (await readContract(options.config, {
|
|
49
|
+
abi: aActionAbi,
|
|
50
|
+
functionName: 'getComponentInterface',
|
|
51
|
+
address,
|
|
52
|
+
})) as keyof typeof ActionByComponentInterface;
|
|
53
|
+
const Ctor = ActionByComponentInterface[interfaceId];
|
|
54
|
+
if (!Ctor) {
|
|
55
|
+
throw new InvalidComponentInterfaceError(
|
|
56
|
+
Object.keys(ActionByComponentInterface) as Hex[],
|
|
57
|
+
interfaceId as Hex,
|
|
58
|
+
);
|
|
59
|
+
}
|
|
60
|
+
return new Ctor(options, address);
|
|
61
|
+
}
|
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
import { mockErc20Abi, readMockErc20BalanceOf } from '@boostxyz/evm';
|
|
2
|
+
import { loadFixture } from '@nomicfoundation/hardhat-network-helpers';
|
|
3
|
+
import { getClient } from '@wagmi/core';
|
|
4
|
+
import {
|
|
5
|
+
ContractFunctionExecutionError,
|
|
6
|
+
encodeAbiParameters,
|
|
7
|
+
encodeFunctionData,
|
|
8
|
+
isAddress,
|
|
9
|
+
parseEther,
|
|
10
|
+
toFunctionSelector,
|
|
11
|
+
zeroAddress,
|
|
12
|
+
} from 'viem';
|
|
13
|
+
import { call } from 'viem/actions';
|
|
14
|
+
import { beforeAll, beforeEach, describe, expect, test } from 'vitest';
|
|
15
|
+
import type { MockERC20 } from '../../test/MockERC20';
|
|
16
|
+
import { accounts } from '../../test/accounts';
|
|
17
|
+
import {
|
|
18
|
+
type Fixtures,
|
|
19
|
+
defaultOptions,
|
|
20
|
+
deployFixtures,
|
|
21
|
+
fundErc20,
|
|
22
|
+
} from '../../test/helpers';
|
|
23
|
+
import { ContractAction } from './ContractAction';
|
|
24
|
+
|
|
25
|
+
let fixtures: Fixtures, erc20: MockERC20;
|
|
26
|
+
|
|
27
|
+
beforeAll(async () => {
|
|
28
|
+
fixtures = await loadFixture(deployFixtures);
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
const mintPayableSelector = toFunctionSelector(
|
|
32
|
+
'function mintPayable(address to, uint256 amount)',
|
|
33
|
+
);
|
|
34
|
+
|
|
35
|
+
const mintSelector = toFunctionSelector(
|
|
36
|
+
'function mint(address to, uint256 amount)',
|
|
37
|
+
);
|
|
38
|
+
|
|
39
|
+
function payableContractAction(fixtures: Fixtures, erc20: MockERC20) {
|
|
40
|
+
return function payableContractAction() {
|
|
41
|
+
return fixtures.registry.clone(
|
|
42
|
+
crypto.randomUUID(),
|
|
43
|
+
new fixtures.bases.ContractAction(defaultOptions, {
|
|
44
|
+
chainId: BigInt(31_337),
|
|
45
|
+
target: erc20.assertValidAddress(),
|
|
46
|
+
selector: mintPayableSelector,
|
|
47
|
+
value: parseEther('0.1'),
|
|
48
|
+
}),
|
|
49
|
+
);
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function nonPayableAction(fixtures: Fixtures, erc20: MockERC20) {
|
|
54
|
+
return function nonPayableAction() {
|
|
55
|
+
return fixtures.registry.clone(
|
|
56
|
+
crypto.randomUUID(),
|
|
57
|
+
new fixtures.bases.ContractAction(defaultOptions, {
|
|
58
|
+
chainId: BigInt(31_337),
|
|
59
|
+
target: erc20.assertValidAddress(),
|
|
60
|
+
selector: mintSelector,
|
|
61
|
+
value: 0n,
|
|
62
|
+
}),
|
|
63
|
+
);
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
function otherAction(fixtures: Fixtures, erc20: MockERC20) {
|
|
68
|
+
return function nonPayableAction() {
|
|
69
|
+
return fixtures.registry.clone(
|
|
70
|
+
crypto.randomUUID(),
|
|
71
|
+
new fixtures.bases.ContractAction(defaultOptions, {
|
|
72
|
+
chainId: BigInt(31_337) + 1n,
|
|
73
|
+
target: erc20.assertValidAddress(),
|
|
74
|
+
selector: mintSelector,
|
|
75
|
+
value: parseEther('0.1'),
|
|
76
|
+
}),
|
|
77
|
+
);
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
describe.skip('ContractAction', () => {
|
|
82
|
+
beforeEach(async () => {
|
|
83
|
+
erc20 = await loadFixture(fundErc20(defaultOptions));
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
test('can successfully be deployed', async () => {
|
|
87
|
+
const action = new ContractAction(defaultOptions, {
|
|
88
|
+
chainId: BigInt(31_337),
|
|
89
|
+
target: zeroAddress,
|
|
90
|
+
selector: '0xdeadbeef',
|
|
91
|
+
value: 2n,
|
|
92
|
+
});
|
|
93
|
+
await action.deploy();
|
|
94
|
+
expect(isAddress(action.assertValidAddress())).toBe(true);
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
test('can read chain id', async () => {
|
|
98
|
+
const action = await loadFixture(payableContractAction(fixtures, erc20));
|
|
99
|
+
expect(await action.chainId()).toBe(BigInt(31_337));
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
test('can read target', async () => {
|
|
103
|
+
const action = await loadFixture(payableContractAction(fixtures, erc20));
|
|
104
|
+
expect((await action.target()).toLowerCase()).toBe(
|
|
105
|
+
erc20.assertValidAddress().toLowerCase(),
|
|
106
|
+
);
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
test('can read selector', async () => {
|
|
110
|
+
const action = await loadFixture(payableContractAction(fixtures, erc20));
|
|
111
|
+
expect(await action.selector()).toBe(mintPayableSelector);
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
test('can read value', async () => {
|
|
115
|
+
const action = await loadFixture(payableContractAction(fixtures, erc20));
|
|
116
|
+
expect(await action.value()).toBe(parseEther('0.1'));
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
test('prepare will properly encode execution payload', async () => {
|
|
120
|
+
const action = await loadFixture(payableContractAction(fixtures, erc20));
|
|
121
|
+
const { account } = accounts.at(1)!;
|
|
122
|
+
const payload = await action.prepare(
|
|
123
|
+
encodeAbiParameters(
|
|
124
|
+
[
|
|
125
|
+
{ type: 'address', name: 'address' },
|
|
126
|
+
{ type: 'uint256', name: 'value' },
|
|
127
|
+
],
|
|
128
|
+
[account, parseEther('100')],
|
|
129
|
+
),
|
|
130
|
+
);
|
|
131
|
+
expect(payload).toBe(
|
|
132
|
+
encodeFunctionData({
|
|
133
|
+
abi: mockErc20Abi,
|
|
134
|
+
functionName: 'mintPayable',
|
|
135
|
+
args: [account, parseEther('100')],
|
|
136
|
+
}),
|
|
137
|
+
);
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
test('payable execute', async () => {
|
|
141
|
+
const action = await loadFixture(payableContractAction(fixtures, erc20));
|
|
142
|
+
const { account } = accounts.at(1)!;
|
|
143
|
+
await action.execute(
|
|
144
|
+
encodeAbiParameters(
|
|
145
|
+
[
|
|
146
|
+
{ type: 'address', name: 'to' },
|
|
147
|
+
{ type: 'uint256', name: 'amount' },
|
|
148
|
+
],
|
|
149
|
+
[account, parseEther('0.1')],
|
|
150
|
+
),
|
|
151
|
+
{ value: parseEther('0.1') },
|
|
152
|
+
);
|
|
153
|
+
expect(
|
|
154
|
+
await readMockErc20BalanceOf(defaultOptions.config, {
|
|
155
|
+
address: erc20.assertValidAddress(),
|
|
156
|
+
args: [account],
|
|
157
|
+
}),
|
|
158
|
+
).toBe(parseEther('0.1'));
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
test('nonpayable execute', async () => {
|
|
162
|
+
const action = await loadFixture(nonPayableAction(fixtures, erc20));
|
|
163
|
+
const { account } = accounts.at(1)!;
|
|
164
|
+
const [success] = await action.execute(
|
|
165
|
+
encodeAbiParameters(
|
|
166
|
+
[
|
|
167
|
+
{ type: 'address', name: 'to' },
|
|
168
|
+
{ type: 'uint256', name: 'amount' },
|
|
169
|
+
],
|
|
170
|
+
[account, parseEther('100')],
|
|
171
|
+
),
|
|
172
|
+
);
|
|
173
|
+
expect(success).toBe(true);
|
|
174
|
+
expect(
|
|
175
|
+
await readMockErc20BalanceOf(defaultOptions.config, {
|
|
176
|
+
address: erc20.assertValidAddress(),
|
|
177
|
+
args: [account],
|
|
178
|
+
}),
|
|
179
|
+
).toBe(parseEther('100'));
|
|
180
|
+
});
|
|
181
|
+
|
|
182
|
+
test('different chain id should throw', async () => {
|
|
183
|
+
const action = await loadFixture(otherAction(fixtures, erc20));
|
|
184
|
+
const { account } = accounts.at(1)!;
|
|
185
|
+
try {
|
|
186
|
+
await action.execute(
|
|
187
|
+
encodeAbiParameters(
|
|
188
|
+
[
|
|
189
|
+
{ type: 'address', name: 'to' },
|
|
190
|
+
{ type: 'uint256', name: 'amount' },
|
|
191
|
+
],
|
|
192
|
+
[account, parseEther('100')],
|
|
193
|
+
),
|
|
194
|
+
);
|
|
195
|
+
} catch (e) {
|
|
196
|
+
expect(e).toBeInstanceOf(ContractFunctionExecutionError);
|
|
197
|
+
}
|
|
198
|
+
});
|
|
199
|
+
});
|
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
import {
|
|
2
|
+
contractActionAbi,
|
|
3
|
+
readContractActionChainId,
|
|
4
|
+
readContractActionPrepare,
|
|
5
|
+
readContractActionSelector,
|
|
6
|
+
readContractActionTarget,
|
|
7
|
+
readContractActionValue,
|
|
8
|
+
simulateContractActionExecute,
|
|
9
|
+
writeContractActionExecute,
|
|
10
|
+
} from '@boostxyz/evm';
|
|
11
|
+
import { bytecode } from '@boostxyz/evm/artifacts/contracts/actions/ContractAction.sol/ContractAction.json';
|
|
12
|
+
import type { Abi, Address, ContractEventName, Hex } from 'viem';
|
|
13
|
+
import type {
|
|
14
|
+
DeployableOptions,
|
|
15
|
+
GenericDeployableParams,
|
|
16
|
+
} from '../Deployable/Deployable';
|
|
17
|
+
import { DeployableTarget } from '../Deployable/DeployableTarget';
|
|
18
|
+
import {
|
|
19
|
+
type ContractActionPayload,
|
|
20
|
+
type GenericLog,
|
|
21
|
+
type ReadParams,
|
|
22
|
+
RegistryType,
|
|
23
|
+
type WriteParams,
|
|
24
|
+
prepareContractActionPayload,
|
|
25
|
+
} from '../utils';
|
|
26
|
+
|
|
27
|
+
export { contractActionAbi };
|
|
28
|
+
export type { ContractActionPayload };
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* A generic `viem.Log` event with support for `ContractAction` event types.
|
|
32
|
+
*
|
|
33
|
+
* @export
|
|
34
|
+
* @typedef {ContractActionLog}
|
|
35
|
+
* @template {ContractEventName<typeof contractActionAbi>} [event=ContractEventName<
|
|
36
|
+
* typeof contractActionAbi
|
|
37
|
+
* >]
|
|
38
|
+
*/
|
|
39
|
+
export type ContractActionLog<
|
|
40
|
+
event extends ContractEventName<typeof contractActionAbi> = ContractEventName<
|
|
41
|
+
typeof contractActionAbi
|
|
42
|
+
>,
|
|
43
|
+
> = GenericLog<typeof contractActionAbi, event>;
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* A generic contract action
|
|
47
|
+
*
|
|
48
|
+
* @export
|
|
49
|
+
* @class ContractAction
|
|
50
|
+
* @typedef {ContractAction}
|
|
51
|
+
* @extends {DeployableTarget<ContractActionPayload>}
|
|
52
|
+
*/
|
|
53
|
+
export class ContractAction<
|
|
54
|
+
ContractActionAbi extends Abi = typeof contractActionAbi,
|
|
55
|
+
> extends DeployableTarget<ContractActionPayload, ContractActionAbi> {
|
|
56
|
+
//@ts-expect-error should never be constructed with variant typ
|
|
57
|
+
public override readonly abi = contractActionAbi;
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* @inheritdoc
|
|
61
|
+
*
|
|
62
|
+
* @public
|
|
63
|
+
* @static
|
|
64
|
+
* @type {Address}
|
|
65
|
+
*/
|
|
66
|
+
public static override base: Address = import.meta.env
|
|
67
|
+
.VITE_CONTRACT_ACTION_BASE;
|
|
68
|
+
/**
|
|
69
|
+
* @inheritdoc
|
|
70
|
+
*
|
|
71
|
+
* @public
|
|
72
|
+
* @static
|
|
73
|
+
* @type {RegistryType}
|
|
74
|
+
*/
|
|
75
|
+
public static override registryType: RegistryType = RegistryType.ACTION;
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* The target chain ID
|
|
79
|
+
*
|
|
80
|
+
* @public
|
|
81
|
+
* @async
|
|
82
|
+
* @param {?ReadParams<typeof contractActionAbi, 'chainId'>} [params]
|
|
83
|
+
* @returns {Promise<bigint>}
|
|
84
|
+
*/
|
|
85
|
+
public async chainId(
|
|
86
|
+
params?: ReadParams<typeof contractActionAbi, 'chainId'>,
|
|
87
|
+
) {
|
|
88
|
+
return readContractActionChainId(this._config, {
|
|
89
|
+
address: this.assertValidAddress(),
|
|
90
|
+
...this.optionallyAttachAccount(),
|
|
91
|
+
// biome-ignore lint/suspicious/noExplicitAny: Accept any shape of valid wagmi/viem parameters, wagmi does the same thing internally
|
|
92
|
+
...(params as any),
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* The target contract
|
|
98
|
+
*
|
|
99
|
+
* @public
|
|
100
|
+
* @async
|
|
101
|
+
* @param {?ReadParams<typeof contractActionAbi, 'target'>} [params]
|
|
102
|
+
* @returns {Promise<`0x${string}`>}
|
|
103
|
+
*/
|
|
104
|
+
public async target(params?: ReadParams<typeof contractActionAbi, 'target'>) {
|
|
105
|
+
return readContractActionTarget(this._config, {
|
|
106
|
+
address: this.assertValidAddress(),
|
|
107
|
+
...this.optionallyAttachAccount(),
|
|
108
|
+
// biome-ignore lint/suspicious/noExplicitAny: Accept any shape of valid wagmi/viem parameters, wagmi does the same thing internally
|
|
109
|
+
...(params as any),
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* The selector for the function to be called
|
|
115
|
+
*
|
|
116
|
+
* @example `function mint(address to, uint256 amount)`
|
|
117
|
+
* @public
|
|
118
|
+
* @async
|
|
119
|
+
* @param {?ReadParams<typeof contractActionAbi, 'selector'>} [params]
|
|
120
|
+
* @returns {Promise<`0x${string}`>}
|
|
121
|
+
*/
|
|
122
|
+
public async selector(
|
|
123
|
+
params?: ReadParams<typeof contractActionAbi, 'selector'>,
|
|
124
|
+
) {
|
|
125
|
+
return readContractActionSelector(this._config, {
|
|
126
|
+
address: this.assertValidAddress(),
|
|
127
|
+
...this.optionallyAttachAccount(),
|
|
128
|
+
// biome-ignore lint/suspicious/noExplicitAny: Accept any shape of valid wagmi/viem parameters, wagmi does the same thing internally
|
|
129
|
+
...(params as any),
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* The native token value to send with the function call
|
|
135
|
+
*
|
|
136
|
+
* @public
|
|
137
|
+
* @async
|
|
138
|
+
* @param {?ReadParams<typeof contractActionAbi, 'value'>} [params]
|
|
139
|
+
* @returns {Promise<bigint>}
|
|
140
|
+
*/
|
|
141
|
+
public async value(params?: ReadParams<typeof contractActionAbi, 'value'>) {
|
|
142
|
+
return readContractActionValue(this._config, {
|
|
143
|
+
address: this.assertValidAddress(),
|
|
144
|
+
...this.optionallyAttachAccount(),
|
|
145
|
+
// biome-ignore lint/suspicious/noExplicitAny: Accept any shape of valid wagmi/viem parameters, wagmi does the same thing internally
|
|
146
|
+
...(params as any),
|
|
147
|
+
});
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* Executes a prepared contract action
|
|
152
|
+
*
|
|
153
|
+
* @public
|
|
154
|
+
* @async
|
|
155
|
+
* @param {Hex} data
|
|
156
|
+
* @param {?WriteParams<typeof contractActionAbi, 'execute'>} [params]
|
|
157
|
+
* @returns {Promise<readonly [boolean, `0x${string}`]>}
|
|
158
|
+
*/
|
|
159
|
+
public async execute(
|
|
160
|
+
data: Hex,
|
|
161
|
+
params?: WriteParams<typeof contractActionAbi, 'execute'>,
|
|
162
|
+
) {
|
|
163
|
+
return this.awaitResult(this.executeRaw(data, params));
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
/**
|
|
167
|
+
* Executes a prepared contract action
|
|
168
|
+
*
|
|
169
|
+
* @public
|
|
170
|
+
* @async
|
|
171
|
+
* @param {Hex} data
|
|
172
|
+
* @param {?WriteParams<typeof contractActionAbi, 'execute'>} [params]
|
|
173
|
+
* @returns {unknown}
|
|
174
|
+
*/
|
|
175
|
+
public async executeRaw(
|
|
176
|
+
data: Hex,
|
|
177
|
+
params?: WriteParams<typeof contractActionAbi, 'execute'>,
|
|
178
|
+
) {
|
|
179
|
+
const { request, result } = await simulateContractActionExecute(
|
|
180
|
+
this._config,
|
|
181
|
+
{
|
|
182
|
+
address: this.assertValidAddress(),
|
|
183
|
+
...this.optionallyAttachAccount(),
|
|
184
|
+
// biome-ignore lint/suspicious/noExplicitAny: Accept any shape of valid wagmi/viem parameters, wagmi does the same thing internally
|
|
185
|
+
...(params as any),
|
|
186
|
+
args: [data],
|
|
187
|
+
},
|
|
188
|
+
);
|
|
189
|
+
const hash = await writeContractActionExecute(this._config, request);
|
|
190
|
+
return { hash, result };
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
/**
|
|
194
|
+
* The encoded execution payload
|
|
195
|
+
*
|
|
196
|
+
* @public
|
|
197
|
+
* @async
|
|
198
|
+
* @param {Hex} calldata
|
|
199
|
+
* @param {?ReadParams<typeof contractActionAbi, 'prepare'>} [params]
|
|
200
|
+
* @returns {unknown}
|
|
201
|
+
*/
|
|
202
|
+
public async prepare(
|
|
203
|
+
calldata: Hex,
|
|
204
|
+
params?: ReadParams<typeof contractActionAbi, 'prepare'>,
|
|
205
|
+
) {
|
|
206
|
+
return readContractActionPrepare(this._config, {
|
|
207
|
+
address: this.assertValidAddress(),
|
|
208
|
+
args: [calldata],
|
|
209
|
+
...this.optionallyAttachAccount(),
|
|
210
|
+
// biome-ignore lint/suspicious/noExplicitAny: Accept any shape of valid wagmi/viem parameters, wagmi does the same thing internally
|
|
211
|
+
...(params as any),
|
|
212
|
+
});
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
/**
|
|
216
|
+
* @inheritdoc
|
|
217
|
+
*
|
|
218
|
+
* @public
|
|
219
|
+
* @param {?ContractActionPayload} [_payload]
|
|
220
|
+
* @param {?DeployableOptions} [_options]
|
|
221
|
+
* @returns {GenericDeployableParams}
|
|
222
|
+
*/
|
|
223
|
+
public override buildParameters(
|
|
224
|
+
_payload?: ContractActionPayload,
|
|
225
|
+
_options?: DeployableOptions,
|
|
226
|
+
): GenericDeployableParams {
|
|
227
|
+
const [payload, options] = this.validateDeploymentConfig(
|
|
228
|
+
_payload,
|
|
229
|
+
_options,
|
|
230
|
+
);
|
|
231
|
+
return {
|
|
232
|
+
abi: contractActionAbi,
|
|
233
|
+
bytecode: bytecode as Hex,
|
|
234
|
+
args: [prepareContractActionPayload(payload)],
|
|
235
|
+
...this.optionallyAttachAccount(options.account),
|
|
236
|
+
};
|
|
237
|
+
}
|
|
238
|
+
}
|