@cowprotocol/sdk-cow-shed 0.1.0-monorepo.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 +142 -0
- package/dist/index.d.mts +131 -0
- package/dist/index.d.ts +131 -0
- package/dist/index.js +337 -0
- package/dist/index.mjs +318 -0
- package/package.json +46 -0
package/README.md
ADDED
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
<p align="center">
|
|
2
|
+
<img width="400" src="https://github.com/cowprotocol/cow-sdk/raw/main/docs/images/CoW.png" />
|
|
3
|
+
</p>
|
|
4
|
+
|
|
5
|
+
# Cow Shed SDK
|
|
6
|
+
|
|
7
|
+
The Cow Shed SDK is a TypeScript library that provides a set of functions to interact with the [Cow Shed contract](https://github.com/cowdao-grants/cow-shed).
|
|
8
|
+
|
|
9
|
+
In essence, CoW Shed acts as a user owned smart contract (1/1 multisig if you will) that can execute multiple calls on behalf of the user (once the user has pre-authorized the calls).
|
|
10
|
+
|
|
11
|
+
## Usage
|
|
12
|
+
|
|
13
|
+
### Individual Package Usage
|
|
14
|
+
|
|
15
|
+
```ts
|
|
16
|
+
import { ethers } from 'ethers'
|
|
17
|
+
import { CowShedSdk, ICoWShedCall, SupportedChainId } from '@cowprotocol/cow-shed'
|
|
18
|
+
import { EthersV6Adapter } from '@cowprotocol/sdk-ethers-v6-adapter'
|
|
19
|
+
import { JsonRpcProvider, Wallet } from 'ethers'
|
|
20
|
+
|
|
21
|
+
// Proper adapter initialization
|
|
22
|
+
const provider = new JsonRpcProvider('YOUR_RPC_URL')
|
|
23
|
+
const wallet = new Wallet('YOUR_PRIVATE_KEY', provider)
|
|
24
|
+
const adapter = new EthersV6Adapter({ provider, signer: wallet })
|
|
25
|
+
|
|
26
|
+
const cowShedSdk = new CowShedSdk(adapter) // adapter is optional - will use global adapter if not provided
|
|
27
|
+
|
|
28
|
+
// Get the cow-shed account for any given chainId and owner's address
|
|
29
|
+
const cowShedAccount = cowShedSdk.getCowShedAccount(1, '0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045')
|
|
30
|
+
|
|
31
|
+
// Prepare the calls you want to execute using the cow-shed account
|
|
32
|
+
const calls: ICoWShedCall[] = [
|
|
33
|
+
{
|
|
34
|
+
target: '<contract-address-1>',
|
|
35
|
+
callData: 'call-data-1',
|
|
36
|
+
value: 0n,
|
|
37
|
+
isDelegateCall: true,
|
|
38
|
+
allowFailure: false,
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
target: '<contract-address-2>',
|
|
42
|
+
callData: '<call-data-2>',
|
|
43
|
+
value: 0n,
|
|
44
|
+
isDelegateCall: true,
|
|
45
|
+
allowFailure: false,
|
|
46
|
+
},
|
|
47
|
+
]
|
|
48
|
+
|
|
49
|
+
// Sign the calls
|
|
50
|
+
const preAuthorizedCall = await cowShedSdk.signCalls({
|
|
51
|
+
chainId: SupportedChainId.MAINNET,
|
|
52
|
+
calls,
|
|
53
|
+
signer: '<privateKeyOrEthersSigner>', // signer is optional - will use global adapter's signer if not provided
|
|
54
|
+
})
|
|
55
|
+
|
|
56
|
+
// Get the details of the pre-authorized call you need to send
|
|
57
|
+
const { signedMulticall, gasLimit, cowShedAccount } = preAuthorizedCall
|
|
58
|
+
const { to, data, value } = signedMulticall
|
|
59
|
+
|
|
60
|
+
// Execute the transaction using any wallet. The calldata has been pre-authed, so you don't need any
|
|
61
|
+
// special permissions to send this transaction
|
|
62
|
+
let anotherWallet = new ethers.Wallet('<another-private-key>')
|
|
63
|
+
const tx = await anotherWallet.sendTransaction({
|
|
64
|
+
to,
|
|
65
|
+
data,
|
|
66
|
+
value,
|
|
67
|
+
gasLimit,
|
|
68
|
+
})
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
### Using via Cow SDK
|
|
72
|
+
|
|
73
|
+
You can also import `CowShedSdk` directly from the main SDK:
|
|
74
|
+
|
|
75
|
+
```ts
|
|
76
|
+
import { ethers } from 'ethers'
|
|
77
|
+
import { CowShedSdk, ICoWShedCall, SupportedChainId } from '@cowprotocol/cow-sdk'
|
|
78
|
+
import { EthersV6Adapter } from '@cowprotocol/sdk-ethers-v6-adapter'
|
|
79
|
+
import { JsonRpcProvider, Wallet } from 'ethers'
|
|
80
|
+
|
|
81
|
+
// Proper adapter initialization
|
|
82
|
+
const provider = new JsonRpcProvider('YOUR_RPC_URL')
|
|
83
|
+
const wallet = new Wallet('YOUR_PRIVATE_KEY', provider)
|
|
84
|
+
const adapter = new EthersV6Adapter({ provider, signer: wallet })
|
|
85
|
+
|
|
86
|
+
const cowShedSdk = new CowShedSdk(adapter) // adapter is optional - will use global adapter if not provided
|
|
87
|
+
// ... rest of the usage remains the same
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
### Using with CowSdk Umbrella
|
|
91
|
+
|
|
92
|
+
For a unified experience with all CoW Protocol modules:
|
|
93
|
+
|
|
94
|
+
```ts
|
|
95
|
+
import { ethers } from 'ethers'
|
|
96
|
+
import { CowSdk, SupportedChainId, ICoWShedCall } from '@cowprotocol/cow-sdk'
|
|
97
|
+
import { EthersV6Adapter } from '@cowprotocol/sdk-ethers-v6-adapter'
|
|
98
|
+
import { JsonRpcProvider, Wallet } from 'ethers'
|
|
99
|
+
|
|
100
|
+
// Proper adapter initialization
|
|
101
|
+
const provider = new JsonRpcProvider('YOUR_RPC_URL')
|
|
102
|
+
const wallet = new Wallet('YOUR_PRIVATE_KEY', provider)
|
|
103
|
+
const adapter = new EthersV6Adapter({ provider, signer: wallet })
|
|
104
|
+
|
|
105
|
+
const cowSdk = new CowSdk({
|
|
106
|
+
adapter,
|
|
107
|
+
chainId: SupportedChainId.MAINNET,
|
|
108
|
+
})
|
|
109
|
+
|
|
110
|
+
// Access cowShed through the umbrella SDK
|
|
111
|
+
const cowShedSdk = cowSdk.cowShed
|
|
112
|
+
|
|
113
|
+
// Prepare the calls you want to execute using the cow-shed account
|
|
114
|
+
const calls: ICoWShedCall[] = [
|
|
115
|
+
{
|
|
116
|
+
target: '<contract-address-1>',
|
|
117
|
+
callData: 'call-data-1',
|
|
118
|
+
value: 0n,
|
|
119
|
+
isDelegateCall: true,
|
|
120
|
+
allowFailure: false,
|
|
121
|
+
},
|
|
122
|
+
]
|
|
123
|
+
|
|
124
|
+
// Sign the calls
|
|
125
|
+
const preAuthorizedCall = await cowShedSdk.signCalls({
|
|
126
|
+
chainId: SupportedChainId.MAINNET,
|
|
127
|
+
calls,
|
|
128
|
+
signer: '<privateKeyOrEthersSigner>', // signer is optional - will use global adapter's signer if not provided
|
|
129
|
+
})
|
|
130
|
+
|
|
131
|
+
// Execute the transaction using any wallet
|
|
132
|
+
const { signedMulticall, gasLimit } = preAuthorizedCall
|
|
133
|
+
const { to, data, value } = signedMulticall
|
|
134
|
+
|
|
135
|
+
let anotherWallet = new ethers.Wallet('<another-private-key>')
|
|
136
|
+
const tx = await anotherWallet.sendTransaction({
|
|
137
|
+
to,
|
|
138
|
+
data,
|
|
139
|
+
value,
|
|
140
|
+
gasLimit,
|
|
141
|
+
})
|
|
142
|
+
```
|
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
import { SupportedChainId, EvmCall } from '@cowprotocol/sdk-config';
|
|
2
|
+
import { ContractsEcdsaSigningScheme } from '@cowprotocol/sdk-contracts-ts';
|
|
3
|
+
import { AbstractProviderAdapter, SignerLike, TypedDataDomain } from '@cowprotocol/sdk-common';
|
|
4
|
+
|
|
5
|
+
interface ICoWShedOptions {
|
|
6
|
+
factoryAddress: string;
|
|
7
|
+
proxyCreationCode?: string;
|
|
8
|
+
implementationAddress: string;
|
|
9
|
+
}
|
|
10
|
+
interface ICoWShedCall {
|
|
11
|
+
target: string;
|
|
12
|
+
value: bigint;
|
|
13
|
+
callData: string;
|
|
14
|
+
allowFailure: boolean;
|
|
15
|
+
isDelegateCall: boolean;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
declare const COW_SHED_PROXY_INIT_CODE = "0x60a034608e57601f61037138819003918201601f19168301916001600160401b038311848410176093578084926040948552833981010312608e57604b602060458360a9565b920160a9565b6080527f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc556040516102b490816100bd8239608051818181608f01526101720152f35b600080fd5b634e487b7160e01b600052604160045260246000fd5b51906001600160a01b0382168203608e5756fe60806040526004361015610018575b3661019457610194565b6000803560e01c908163025b22bc1461003b575063f851a4400361000e5761010d565b3461010a5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261010a5773ffffffffffffffffffffffffffffffffffffffff60043581811691828203610106577f0000000000000000000000000000000000000000000000000000000000000000163314600014610101577f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc557fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b8280a280f35b61023d565b8380fd5b80fd5b346101645760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610164576020610146610169565b73ffffffffffffffffffffffffffffffffffffffff60405191168152f35b600080fd5b333003610101577f000000000000000000000000000000000000000000000000000000000000000090565b60ff7f68df44b1011761f481358c0f49a711192727fb02c377d697bcb0ea8ff8393ac0541615806101ef575b1561023d5760046040517ff92ee8a9000000000000000000000000000000000000000000000000000000008152fd5b507f400ada75000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000006000351614156101c0565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc546000808092368280378136915af43d82803e1561027a573d90f35b3d90fdfea2646970667358221220c7c26ff3040b96a28e96d6d27b743972943aeaef81cc821544c5fe1e24f9b17264736f6c63430008190033";
|
|
19
|
+
declare const COW_SHED_712_TYPES: {
|
|
20
|
+
ExecuteHooks: {
|
|
21
|
+
type: string;
|
|
22
|
+
name: string;
|
|
23
|
+
}[];
|
|
24
|
+
Call: {
|
|
25
|
+
type: string;
|
|
26
|
+
name: string;
|
|
27
|
+
}[];
|
|
28
|
+
};
|
|
29
|
+
declare class CowShedHooks {
|
|
30
|
+
private chainId;
|
|
31
|
+
private customOptions?;
|
|
32
|
+
constructor(chainId: SupportedChainId, customOptions?: ICoWShedOptions | undefined, adapter?: AbstractProviderAdapter);
|
|
33
|
+
proxyOf(user: string): string;
|
|
34
|
+
encodeExecuteHooksForFactory(calls: ICoWShedCall[], nonce: string, deadline: bigint, ownerAddress: string, signature: string): string;
|
|
35
|
+
signCalls(calls: ICoWShedCall[], nonce: string, deadline: bigint, signingScheme: ContractsEcdsaSigningScheme, owner?: SignerLike): Promise<string>;
|
|
36
|
+
infoToSign(calls: ICoWShedCall[], nonce: string, deadline: bigint, proxy: string): {
|
|
37
|
+
domain: unknown;
|
|
38
|
+
types: {
|
|
39
|
+
ExecuteHooks: {
|
|
40
|
+
type: string;
|
|
41
|
+
name: string;
|
|
42
|
+
}[];
|
|
43
|
+
Call: {
|
|
44
|
+
type: string;
|
|
45
|
+
name: string;
|
|
46
|
+
}[];
|
|
47
|
+
};
|
|
48
|
+
message: {
|
|
49
|
+
calls: {
|
|
50
|
+
target: string;
|
|
51
|
+
value: bigint;
|
|
52
|
+
callData: string;
|
|
53
|
+
allowFailure: boolean;
|
|
54
|
+
isDelegateCall: boolean;
|
|
55
|
+
}[];
|
|
56
|
+
nonce: string;
|
|
57
|
+
deadline: string;
|
|
58
|
+
};
|
|
59
|
+
};
|
|
60
|
+
getDomain(proxy: string): TypedDataDomain;
|
|
61
|
+
proxyCreationCode(): string;
|
|
62
|
+
getFactoryAddress(): string;
|
|
63
|
+
getImplementationAddress(): string;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
interface SignAndEncodeTxArgs {
|
|
67
|
+
/**
|
|
68
|
+
* Calls to pre-authorize on the cow-shed account
|
|
69
|
+
*/
|
|
70
|
+
calls: ICoWShedCall[];
|
|
71
|
+
/**
|
|
72
|
+
* Signer for the cow-shed's owner account.
|
|
73
|
+
*
|
|
74
|
+
* The signer will be used to pre-authorise the calls.
|
|
75
|
+
* The cow-shed account will be derived from this signer.
|
|
76
|
+
*/
|
|
77
|
+
signer?: SignerLike;
|
|
78
|
+
/**
|
|
79
|
+
* Chain ID to use for the transaction.
|
|
80
|
+
*/
|
|
81
|
+
chainId: SupportedChainId;
|
|
82
|
+
/**
|
|
83
|
+
* Nonce to use for the transaction. If not provided, the current timestamp will be used.
|
|
84
|
+
*/
|
|
85
|
+
nonce?: string;
|
|
86
|
+
/**
|
|
87
|
+
* Deadline to use for the transaction. If not provided, the maximum uint256 will be used.
|
|
88
|
+
*/
|
|
89
|
+
deadline?: bigint;
|
|
90
|
+
/**
|
|
91
|
+
* Default gas limit to use for the transaction. If not provided, it will throw an error if the gas limit cannot be estimated.
|
|
92
|
+
*/
|
|
93
|
+
defaultGasLimit?: bigint;
|
|
94
|
+
/**
|
|
95
|
+
* Signing scheme to use for the transaction.
|
|
96
|
+
*/
|
|
97
|
+
signingScheme?: ContractsEcdsaSigningScheme;
|
|
98
|
+
}
|
|
99
|
+
interface CowShedCall {
|
|
100
|
+
cowShedAccount: string;
|
|
101
|
+
signedMulticall: EvmCall;
|
|
102
|
+
gasLimit: bigint;
|
|
103
|
+
}
|
|
104
|
+
interface CowShedSdkOptions {
|
|
105
|
+
/**
|
|
106
|
+
* Optional adapter for the cow-shed, if not provided, the global adapter will be used.
|
|
107
|
+
*/
|
|
108
|
+
adapter?: AbstractProviderAdapter;
|
|
109
|
+
/**
|
|
110
|
+
* Custom options for the cow-shed hooks.
|
|
111
|
+
*/
|
|
112
|
+
factoryOptions?: ICoWShedOptions;
|
|
113
|
+
}
|
|
114
|
+
declare class CowShedSdk {
|
|
115
|
+
private factoryOptions?;
|
|
116
|
+
protected hooksCache: Map<SupportedChainId, CowShedHooks>;
|
|
117
|
+
constructor(adapter?: AbstractProviderAdapter, factoryOptions?: ICoWShedOptions | undefined);
|
|
118
|
+
getCowShedAccount(chainId: SupportedChainId, ownerAddress: string): string;
|
|
119
|
+
/**
|
|
120
|
+
* Encodes multiple calls into a single pre-authorized call to the cow-shed factory.
|
|
121
|
+
*
|
|
122
|
+
* This single call will create the cow-shed account if it doesn't exist yet, then will execute the calls.
|
|
123
|
+
*
|
|
124
|
+
* @returns pre-authorized multicall details
|
|
125
|
+
*/
|
|
126
|
+
signCalls({ calls, signer: signerParam, chainId, nonce, deadline, defaultGasLimit, signingScheme, }: SignAndEncodeTxArgs): Promise<CowShedCall>;
|
|
127
|
+
protected getCowShedHooks(chainId: SupportedChainId, customOptions?: ICoWShedOptions): CowShedHooks;
|
|
128
|
+
protected static getNonce(): string;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
export { COW_SHED_712_TYPES, COW_SHED_PROXY_INIT_CODE, type CowShedCall, CowShedHooks, CowShedSdk, type CowShedSdkOptions, type ICoWShedCall, type ICoWShedOptions, type SignAndEncodeTxArgs };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
import { SupportedChainId, EvmCall } from '@cowprotocol/sdk-config';
|
|
2
|
+
import { ContractsEcdsaSigningScheme } from '@cowprotocol/sdk-contracts-ts';
|
|
3
|
+
import { AbstractProviderAdapter, SignerLike, TypedDataDomain } from '@cowprotocol/sdk-common';
|
|
4
|
+
|
|
5
|
+
interface ICoWShedOptions {
|
|
6
|
+
factoryAddress: string;
|
|
7
|
+
proxyCreationCode?: string;
|
|
8
|
+
implementationAddress: string;
|
|
9
|
+
}
|
|
10
|
+
interface ICoWShedCall {
|
|
11
|
+
target: string;
|
|
12
|
+
value: bigint;
|
|
13
|
+
callData: string;
|
|
14
|
+
allowFailure: boolean;
|
|
15
|
+
isDelegateCall: boolean;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
declare const COW_SHED_PROXY_INIT_CODE = "0x60a034608e57601f61037138819003918201601f19168301916001600160401b038311848410176093578084926040948552833981010312608e57604b602060458360a9565b920160a9565b6080527f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc556040516102b490816100bd8239608051818181608f01526101720152f35b600080fd5b634e487b7160e01b600052604160045260246000fd5b51906001600160a01b0382168203608e5756fe60806040526004361015610018575b3661019457610194565b6000803560e01c908163025b22bc1461003b575063f851a4400361000e5761010d565b3461010a5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261010a5773ffffffffffffffffffffffffffffffffffffffff60043581811691828203610106577f0000000000000000000000000000000000000000000000000000000000000000163314600014610101577f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc557fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b8280a280f35b61023d565b8380fd5b80fd5b346101645760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610164576020610146610169565b73ffffffffffffffffffffffffffffffffffffffff60405191168152f35b600080fd5b333003610101577f000000000000000000000000000000000000000000000000000000000000000090565b60ff7f68df44b1011761f481358c0f49a711192727fb02c377d697bcb0ea8ff8393ac0541615806101ef575b1561023d5760046040517ff92ee8a9000000000000000000000000000000000000000000000000000000008152fd5b507f400ada75000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000006000351614156101c0565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc546000808092368280378136915af43d82803e1561027a573d90f35b3d90fdfea2646970667358221220c7c26ff3040b96a28e96d6d27b743972943aeaef81cc821544c5fe1e24f9b17264736f6c63430008190033";
|
|
19
|
+
declare const COW_SHED_712_TYPES: {
|
|
20
|
+
ExecuteHooks: {
|
|
21
|
+
type: string;
|
|
22
|
+
name: string;
|
|
23
|
+
}[];
|
|
24
|
+
Call: {
|
|
25
|
+
type: string;
|
|
26
|
+
name: string;
|
|
27
|
+
}[];
|
|
28
|
+
};
|
|
29
|
+
declare class CowShedHooks {
|
|
30
|
+
private chainId;
|
|
31
|
+
private customOptions?;
|
|
32
|
+
constructor(chainId: SupportedChainId, customOptions?: ICoWShedOptions | undefined, adapter?: AbstractProviderAdapter);
|
|
33
|
+
proxyOf(user: string): string;
|
|
34
|
+
encodeExecuteHooksForFactory(calls: ICoWShedCall[], nonce: string, deadline: bigint, ownerAddress: string, signature: string): string;
|
|
35
|
+
signCalls(calls: ICoWShedCall[], nonce: string, deadline: bigint, signingScheme: ContractsEcdsaSigningScheme, owner?: SignerLike): Promise<string>;
|
|
36
|
+
infoToSign(calls: ICoWShedCall[], nonce: string, deadline: bigint, proxy: string): {
|
|
37
|
+
domain: unknown;
|
|
38
|
+
types: {
|
|
39
|
+
ExecuteHooks: {
|
|
40
|
+
type: string;
|
|
41
|
+
name: string;
|
|
42
|
+
}[];
|
|
43
|
+
Call: {
|
|
44
|
+
type: string;
|
|
45
|
+
name: string;
|
|
46
|
+
}[];
|
|
47
|
+
};
|
|
48
|
+
message: {
|
|
49
|
+
calls: {
|
|
50
|
+
target: string;
|
|
51
|
+
value: bigint;
|
|
52
|
+
callData: string;
|
|
53
|
+
allowFailure: boolean;
|
|
54
|
+
isDelegateCall: boolean;
|
|
55
|
+
}[];
|
|
56
|
+
nonce: string;
|
|
57
|
+
deadline: string;
|
|
58
|
+
};
|
|
59
|
+
};
|
|
60
|
+
getDomain(proxy: string): TypedDataDomain;
|
|
61
|
+
proxyCreationCode(): string;
|
|
62
|
+
getFactoryAddress(): string;
|
|
63
|
+
getImplementationAddress(): string;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
interface SignAndEncodeTxArgs {
|
|
67
|
+
/**
|
|
68
|
+
* Calls to pre-authorize on the cow-shed account
|
|
69
|
+
*/
|
|
70
|
+
calls: ICoWShedCall[];
|
|
71
|
+
/**
|
|
72
|
+
* Signer for the cow-shed's owner account.
|
|
73
|
+
*
|
|
74
|
+
* The signer will be used to pre-authorise the calls.
|
|
75
|
+
* The cow-shed account will be derived from this signer.
|
|
76
|
+
*/
|
|
77
|
+
signer?: SignerLike;
|
|
78
|
+
/**
|
|
79
|
+
* Chain ID to use for the transaction.
|
|
80
|
+
*/
|
|
81
|
+
chainId: SupportedChainId;
|
|
82
|
+
/**
|
|
83
|
+
* Nonce to use for the transaction. If not provided, the current timestamp will be used.
|
|
84
|
+
*/
|
|
85
|
+
nonce?: string;
|
|
86
|
+
/**
|
|
87
|
+
* Deadline to use for the transaction. If not provided, the maximum uint256 will be used.
|
|
88
|
+
*/
|
|
89
|
+
deadline?: bigint;
|
|
90
|
+
/**
|
|
91
|
+
* Default gas limit to use for the transaction. If not provided, it will throw an error if the gas limit cannot be estimated.
|
|
92
|
+
*/
|
|
93
|
+
defaultGasLimit?: bigint;
|
|
94
|
+
/**
|
|
95
|
+
* Signing scheme to use for the transaction.
|
|
96
|
+
*/
|
|
97
|
+
signingScheme?: ContractsEcdsaSigningScheme;
|
|
98
|
+
}
|
|
99
|
+
interface CowShedCall {
|
|
100
|
+
cowShedAccount: string;
|
|
101
|
+
signedMulticall: EvmCall;
|
|
102
|
+
gasLimit: bigint;
|
|
103
|
+
}
|
|
104
|
+
interface CowShedSdkOptions {
|
|
105
|
+
/**
|
|
106
|
+
* Optional adapter for the cow-shed, if not provided, the global adapter will be used.
|
|
107
|
+
*/
|
|
108
|
+
adapter?: AbstractProviderAdapter;
|
|
109
|
+
/**
|
|
110
|
+
* Custom options for the cow-shed hooks.
|
|
111
|
+
*/
|
|
112
|
+
factoryOptions?: ICoWShedOptions;
|
|
113
|
+
}
|
|
114
|
+
declare class CowShedSdk {
|
|
115
|
+
private factoryOptions?;
|
|
116
|
+
protected hooksCache: Map<SupportedChainId, CowShedHooks>;
|
|
117
|
+
constructor(adapter?: AbstractProviderAdapter, factoryOptions?: ICoWShedOptions | undefined);
|
|
118
|
+
getCowShedAccount(chainId: SupportedChainId, ownerAddress: string): string;
|
|
119
|
+
/**
|
|
120
|
+
* Encodes multiple calls into a single pre-authorized call to the cow-shed factory.
|
|
121
|
+
*
|
|
122
|
+
* This single call will create the cow-shed account if it doesn't exist yet, then will execute the calls.
|
|
123
|
+
*
|
|
124
|
+
* @returns pre-authorized multicall details
|
|
125
|
+
*/
|
|
126
|
+
signCalls({ calls, signer: signerParam, chainId, nonce, deadline, defaultGasLimit, signingScheme, }: SignAndEncodeTxArgs): Promise<CowShedCall>;
|
|
127
|
+
protected getCowShedHooks(chainId: SupportedChainId, customOptions?: ICoWShedOptions): CowShedHooks;
|
|
128
|
+
protected static getNonce(): string;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
export { COW_SHED_712_TYPES, COW_SHED_PROXY_INIT_CODE, type CowShedCall, CowShedHooks, CowShedSdk, type CowShedSdkOptions, type ICoWShedCall, type ICoWShedOptions, type SignAndEncodeTxArgs };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,337 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/index.ts
|
|
21
|
+
var src_exports = {};
|
|
22
|
+
__export(src_exports, {
|
|
23
|
+
COW_SHED_712_TYPES: () => COW_SHED_712_TYPES,
|
|
24
|
+
COW_SHED_PROXY_INIT_CODE: () => COW_SHED_PROXY_INIT_CODE,
|
|
25
|
+
CowShedHooks: () => CowShedHooks,
|
|
26
|
+
CowShedSdk: () => CowShedSdk
|
|
27
|
+
});
|
|
28
|
+
module.exports = __toCommonJS(src_exports);
|
|
29
|
+
|
|
30
|
+
// src/contracts/CoWShedHooks.ts
|
|
31
|
+
var import_sdk_contracts_ts = require("@cowprotocol/sdk-contracts-ts");
|
|
32
|
+
var import_sdk_config = require("@cowprotocol/sdk-config");
|
|
33
|
+
var import_sdk_common = require("@cowprotocol/sdk-common");
|
|
34
|
+
|
|
35
|
+
// src/abi/CowShedFactoryAbi.ts
|
|
36
|
+
var CowShedFactoryAbi = [
|
|
37
|
+
{
|
|
38
|
+
inputs: [
|
|
39
|
+
{ internalType: "address", name: "impl", type: "address" },
|
|
40
|
+
{ internalType: "bytes32", name: "bName", type: "bytes32" },
|
|
41
|
+
{ internalType: "bytes32", name: "bNode", type: "bytes32" }
|
|
42
|
+
],
|
|
43
|
+
stateMutability: "nonpayable",
|
|
44
|
+
type: "constructor"
|
|
45
|
+
},
|
|
46
|
+
{ inputs: [], name: "InvalidSignature", type: "error" },
|
|
47
|
+
{ inputs: [], name: "NonceAlreadyUsed", type: "error" },
|
|
48
|
+
{ inputs: [], name: "SettingEnsRecordsFailed", type: "error" },
|
|
49
|
+
{
|
|
50
|
+
anonymous: false,
|
|
51
|
+
inputs: [
|
|
52
|
+
{ indexed: false, internalType: "address", name: "user", type: "address" },
|
|
53
|
+
{ indexed: false, internalType: "address", name: "shed", type: "address" }
|
|
54
|
+
],
|
|
55
|
+
name: "COWShedBuilt",
|
|
56
|
+
type: "event"
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
inputs: [{ internalType: "bytes32", name: "node", type: "bytes32" }],
|
|
60
|
+
name: "addr",
|
|
61
|
+
outputs: [{ internalType: "address", name: "", type: "address" }],
|
|
62
|
+
stateMutability: "view",
|
|
63
|
+
type: "function"
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
inputs: [],
|
|
67
|
+
name: "baseName",
|
|
68
|
+
outputs: [{ internalType: "string", name: "", type: "string" }],
|
|
69
|
+
stateMutability: "view",
|
|
70
|
+
type: "function"
|
|
71
|
+
},
|
|
72
|
+
{
|
|
73
|
+
inputs: [],
|
|
74
|
+
name: "baseNode",
|
|
75
|
+
outputs: [{ internalType: "bytes32", name: "", type: "bytes32" }],
|
|
76
|
+
stateMutability: "view",
|
|
77
|
+
type: "function"
|
|
78
|
+
},
|
|
79
|
+
{
|
|
80
|
+
inputs: [
|
|
81
|
+
{
|
|
82
|
+
components: [
|
|
83
|
+
{ internalType: "address", name: "target", type: "address" },
|
|
84
|
+
{ internalType: "uint256", name: "value", type: "uint256" },
|
|
85
|
+
{ internalType: "bytes", name: "callData", type: "bytes" },
|
|
86
|
+
{ internalType: "bool", name: "allowFailure", type: "bool" },
|
|
87
|
+
{ internalType: "bool", name: "isDelegateCall", type: "bool" }
|
|
88
|
+
],
|
|
89
|
+
internalType: "struct Call[]",
|
|
90
|
+
name: "calls",
|
|
91
|
+
type: "tuple[]"
|
|
92
|
+
},
|
|
93
|
+
{ internalType: "bytes32", name: "nonce", type: "bytes32" },
|
|
94
|
+
{ internalType: "uint256", name: "deadline", type: "uint256" },
|
|
95
|
+
{ internalType: "address", name: "user", type: "address" },
|
|
96
|
+
{ internalType: "bytes", name: "signature", type: "bytes" }
|
|
97
|
+
],
|
|
98
|
+
name: "executeHooks",
|
|
99
|
+
outputs: [],
|
|
100
|
+
stateMutability: "nonpayable",
|
|
101
|
+
type: "function"
|
|
102
|
+
},
|
|
103
|
+
{
|
|
104
|
+
inputs: [{ internalType: "bytes32", name: "", type: "bytes32" }],
|
|
105
|
+
name: "forwardResolutionNodeToAddress",
|
|
106
|
+
outputs: [{ internalType: "address", name: "", type: "address" }],
|
|
107
|
+
stateMutability: "view",
|
|
108
|
+
type: "function"
|
|
109
|
+
},
|
|
110
|
+
{
|
|
111
|
+
inputs: [],
|
|
112
|
+
name: "implementation",
|
|
113
|
+
outputs: [{ internalType: "address", name: "", type: "address" }],
|
|
114
|
+
stateMutability: "view",
|
|
115
|
+
type: "function"
|
|
116
|
+
},
|
|
117
|
+
{
|
|
118
|
+
inputs: [{ internalType: "address", name: "user", type: "address" }],
|
|
119
|
+
name: "initializeEns",
|
|
120
|
+
outputs: [],
|
|
121
|
+
stateMutability: "nonpayable",
|
|
122
|
+
type: "function"
|
|
123
|
+
},
|
|
124
|
+
{
|
|
125
|
+
inputs: [
|
|
126
|
+
{ internalType: "address", name: "user", type: "address" },
|
|
127
|
+
{ internalType: "bool", name: "withEns", type: "bool" }
|
|
128
|
+
],
|
|
129
|
+
name: "initializeProxy",
|
|
130
|
+
outputs: [],
|
|
131
|
+
stateMutability: "nonpayable",
|
|
132
|
+
type: "function"
|
|
133
|
+
},
|
|
134
|
+
{
|
|
135
|
+
inputs: [{ internalType: "bytes32", name: "node", type: "bytes32" }],
|
|
136
|
+
name: "name",
|
|
137
|
+
outputs: [{ internalType: "string", name: "", type: "string" }],
|
|
138
|
+
stateMutability: "view",
|
|
139
|
+
type: "function"
|
|
140
|
+
},
|
|
141
|
+
{
|
|
142
|
+
inputs: [{ internalType: "address", name: "", type: "address" }],
|
|
143
|
+
name: "ownerOf",
|
|
144
|
+
outputs: [{ internalType: "address", name: "", type: "address" }],
|
|
145
|
+
stateMutability: "view",
|
|
146
|
+
type: "function"
|
|
147
|
+
},
|
|
148
|
+
{
|
|
149
|
+
inputs: [{ internalType: "address", name: "who", type: "address" }],
|
|
150
|
+
name: "proxyOf",
|
|
151
|
+
outputs: [{ internalType: "address", name: "", type: "address" }],
|
|
152
|
+
stateMutability: "view",
|
|
153
|
+
type: "function"
|
|
154
|
+
},
|
|
155
|
+
{
|
|
156
|
+
inputs: [{ internalType: "bytes32", name: "", type: "bytes32" }],
|
|
157
|
+
name: "reverseResolutionNodeToAddress",
|
|
158
|
+
outputs: [{ internalType: "address", name: "", type: "address" }],
|
|
159
|
+
stateMutability: "view",
|
|
160
|
+
type: "function"
|
|
161
|
+
},
|
|
162
|
+
{
|
|
163
|
+
inputs: [{ internalType: "bytes4", name: "interfaceId", type: "bytes4" }],
|
|
164
|
+
name: "supportsInterface",
|
|
165
|
+
outputs: [{ internalType: "bool", name: "", type: "bool" }],
|
|
166
|
+
stateMutability: "pure",
|
|
167
|
+
type: "function"
|
|
168
|
+
}
|
|
169
|
+
];
|
|
170
|
+
|
|
171
|
+
// src/contracts/CoWShedHooks.ts
|
|
172
|
+
var COW_SHED_PROXY_INIT_CODE = "0x60a034608e57601f61037138819003918201601f19168301916001600160401b038311848410176093578084926040948552833981010312608e57604b602060458360a9565b920160a9565b6080527f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc556040516102b490816100bd8239608051818181608f01526101720152f35b600080fd5b634e487b7160e01b600052604160045260246000fd5b51906001600160a01b0382168203608e5756fe60806040526004361015610018575b3661019457610194565b6000803560e01c908163025b22bc1461003b575063f851a4400361000e5761010d565b3461010a5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261010a5773ffffffffffffffffffffffffffffffffffffffff60043581811691828203610106577f0000000000000000000000000000000000000000000000000000000000000000163314600014610101577f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc557fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b8280a280f35b61023d565b8380fd5b80fd5b346101645760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610164576020610146610169565b73ffffffffffffffffffffffffffffffffffffffff60405191168152f35b600080fd5b333003610101577f000000000000000000000000000000000000000000000000000000000000000090565b60ff7f68df44b1011761f481358c0f49a711192727fb02c377d697bcb0ea8ff8393ac0541615806101ef575b1561023d5760046040517ff92ee8a9000000000000000000000000000000000000000000000000000000008152fd5b507f400ada75000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000006000351614156101c0565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc546000808092368280378136915af43d82803e1561027a573d90f35b3d90fdfea2646970667358221220c7c26ff3040b96a28e96d6d27b743972943aeaef81cc821544c5fe1e24f9b17264736f6c63430008190033";
|
|
173
|
+
var COW_SHED_712_TYPES = {
|
|
174
|
+
ExecuteHooks: [
|
|
175
|
+
{ type: "Call[]", name: "calls" },
|
|
176
|
+
{ type: "bytes32", name: "nonce" },
|
|
177
|
+
{ type: "uint256", name: "deadline" }
|
|
178
|
+
],
|
|
179
|
+
Call: [
|
|
180
|
+
{ type: "address", name: "target" },
|
|
181
|
+
{ type: "uint256", name: "value" },
|
|
182
|
+
{ type: "bytes", name: "callData" },
|
|
183
|
+
{ type: "bool", name: "allowFailure" },
|
|
184
|
+
{ type: "bool", name: "isDelegateCall" }
|
|
185
|
+
]
|
|
186
|
+
};
|
|
187
|
+
var CowShedHooks = class {
|
|
188
|
+
constructor(chainId, customOptions, adapter) {
|
|
189
|
+
this.chainId = chainId;
|
|
190
|
+
this.customOptions = customOptions;
|
|
191
|
+
if (adapter) {
|
|
192
|
+
(0, import_sdk_common.setGlobalAdapter)(adapter);
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
proxyOf(user) {
|
|
196
|
+
const adapter = (0, import_sdk_common.getGlobalAdapter)();
|
|
197
|
+
const salt = adapter.utils.encodeAbi(["address"], [user]);
|
|
198
|
+
const initCodeHash = adapter.utils.solidityKeccak256(
|
|
199
|
+
["bytes", "bytes"],
|
|
200
|
+
[
|
|
201
|
+
this.proxyCreationCode(),
|
|
202
|
+
adapter.utils.encodeAbi(["address", "address"], [this.getImplementationAddress(), user])
|
|
203
|
+
]
|
|
204
|
+
);
|
|
205
|
+
return adapter.utils.getCreate2Address(this.getFactoryAddress(), salt, initCodeHash);
|
|
206
|
+
}
|
|
207
|
+
encodeExecuteHooksForFactory(calls, nonce, deadline, ownerAddress, signature) {
|
|
208
|
+
const adapter = (0, import_sdk_common.getGlobalAdapter)();
|
|
209
|
+
return adapter.utils.encodeFunction(CowShedFactoryAbi, "executeHooks", [
|
|
210
|
+
calls,
|
|
211
|
+
nonce,
|
|
212
|
+
deadline,
|
|
213
|
+
ownerAddress,
|
|
214
|
+
signature
|
|
215
|
+
]);
|
|
216
|
+
}
|
|
217
|
+
async signCalls(calls, nonce, deadline, signingScheme, owner) {
|
|
218
|
+
const adapter = (0, import_sdk_common.getGlobalAdapter)();
|
|
219
|
+
const signer = owner ? adapter.createSigner(owner) : adapter.signer;
|
|
220
|
+
const user = await signer.getAddress();
|
|
221
|
+
const proxy = this.proxyOf(user);
|
|
222
|
+
const { domain, types, message } = this.infoToSign(calls, nonce, deadline, proxy);
|
|
223
|
+
return await (0, import_sdk_contracts_ts.ecdsaSignTypedData)(signingScheme, domain, types, message, signer);
|
|
224
|
+
}
|
|
225
|
+
infoToSign(calls, nonce, deadline, proxy) {
|
|
226
|
+
const message = {
|
|
227
|
+
calls: calls.map((call) => ({
|
|
228
|
+
target: call.target.toLowerCase(),
|
|
229
|
+
value: call.value,
|
|
230
|
+
callData: call.callData,
|
|
231
|
+
allowFailure: call.allowFailure,
|
|
232
|
+
isDelegateCall: call.isDelegateCall
|
|
233
|
+
})),
|
|
234
|
+
nonce,
|
|
235
|
+
deadline: deadline.toString()
|
|
236
|
+
};
|
|
237
|
+
return { domain: this.getDomain(proxy), types: COW_SHED_712_TYPES, message };
|
|
238
|
+
}
|
|
239
|
+
getDomain(proxy) {
|
|
240
|
+
return {
|
|
241
|
+
name: "COWShed",
|
|
242
|
+
version: "1.0.0",
|
|
243
|
+
chainId: typeof this.chainId === "bigint" ? Number(this.chainId) : this.chainId,
|
|
244
|
+
verifyingContract: proxy.toLowerCase()
|
|
245
|
+
};
|
|
246
|
+
}
|
|
247
|
+
proxyCreationCode() {
|
|
248
|
+
return this.customOptions?.proxyCreationCode ?? COW_SHED_PROXY_INIT_CODE;
|
|
249
|
+
}
|
|
250
|
+
getFactoryAddress() {
|
|
251
|
+
return this.customOptions?.factoryAddress ?? import_sdk_config.COW_SHED_FACTORY;
|
|
252
|
+
}
|
|
253
|
+
getImplementationAddress() {
|
|
254
|
+
return this.customOptions?.implementationAddress ?? import_sdk_config.COW_SHED_IMPLEMENTATION;
|
|
255
|
+
}
|
|
256
|
+
};
|
|
257
|
+
|
|
258
|
+
// src/CowShedSdk.ts
|
|
259
|
+
var import_sdk_contracts_ts2 = require("@cowprotocol/sdk-contracts-ts");
|
|
260
|
+
var import_sdk_common2 = require("@cowprotocol/sdk-common");
|
|
261
|
+
var CowShedSdk = class _CowShedSdk {
|
|
262
|
+
constructor(adapter, factoryOptions) {
|
|
263
|
+
this.factoryOptions = factoryOptions;
|
|
264
|
+
if (adapter) {
|
|
265
|
+
(0, import_sdk_common2.setGlobalAdapter)(adapter);
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
hooksCache = /* @__PURE__ */ new Map();
|
|
269
|
+
getCowShedAccount(chainId, ownerAddress) {
|
|
270
|
+
const cowShedHooks = this.getCowShedHooks(chainId, this.factoryOptions);
|
|
271
|
+
return cowShedHooks.proxyOf(ownerAddress);
|
|
272
|
+
}
|
|
273
|
+
/**
|
|
274
|
+
* Encodes multiple calls into a single pre-authorized call to the cow-shed factory.
|
|
275
|
+
*
|
|
276
|
+
* This single call will create the cow-shed account if it doesn't exist yet, then will execute the calls.
|
|
277
|
+
*
|
|
278
|
+
* @returns pre-authorized multicall details
|
|
279
|
+
*/
|
|
280
|
+
async signCalls({
|
|
281
|
+
calls,
|
|
282
|
+
signer: signerParam,
|
|
283
|
+
chainId,
|
|
284
|
+
nonce = _CowShedSdk.getNonce(),
|
|
285
|
+
deadline = import_sdk_common2.MAX_UINT256,
|
|
286
|
+
defaultGasLimit,
|
|
287
|
+
signingScheme = import_sdk_contracts_ts2.ContractsSigningScheme.EIP712
|
|
288
|
+
}) {
|
|
289
|
+
const cowShedHooks = this.getCowShedHooks(chainId);
|
|
290
|
+
const adapter = (0, import_sdk_common2.getGlobalAdapter)();
|
|
291
|
+
const signer = signerParam ? adapter.createSigner(signerParam) : adapter.signer;
|
|
292
|
+
const ownerAddress = await signer.getAddress();
|
|
293
|
+
const cowShedAccount = cowShedHooks.proxyOf(ownerAddress);
|
|
294
|
+
const signature = await cowShedHooks.signCalls(calls, nonce, deadline, signingScheme, signer);
|
|
295
|
+
const callData = cowShedHooks.encodeExecuteHooksForFactory(calls, nonce, deadline, ownerAddress, signature);
|
|
296
|
+
const cowShedFactoryAddress = cowShedHooks.getFactoryAddress();
|
|
297
|
+
const factoryCall = {
|
|
298
|
+
to: cowShedFactoryAddress,
|
|
299
|
+
data: callData,
|
|
300
|
+
value: BigInt(0)
|
|
301
|
+
};
|
|
302
|
+
const gasEstimate = await signer.estimateGas(factoryCall).catch((error) => {
|
|
303
|
+
const factoryCallString = JSON.stringify(factoryCall, import_sdk_common2.jsonWithBigintReplacer, 2);
|
|
304
|
+
const errorMessage = `Error estimating gas for the cow-shed call: ${factoryCallString}. Review the factory call`;
|
|
305
|
+
if (defaultGasLimit) {
|
|
306
|
+
(0, import_sdk_common2.log)(`${errorMessage}, using the default gas limit.`);
|
|
307
|
+
return defaultGasLimit;
|
|
308
|
+
}
|
|
309
|
+
throw new Error(`${errorMessage}, or provide the defaultGasLimit parameter.`, { cause: error });
|
|
310
|
+
});
|
|
311
|
+
return {
|
|
312
|
+
cowShedAccount,
|
|
313
|
+
signedMulticall: factoryCall,
|
|
314
|
+
gasLimit: gasEstimate
|
|
315
|
+
};
|
|
316
|
+
}
|
|
317
|
+
getCowShedHooks(chainId, customOptions) {
|
|
318
|
+
let cowShedHooks = this.hooksCache.get(chainId);
|
|
319
|
+
if (cowShedHooks) {
|
|
320
|
+
return cowShedHooks;
|
|
321
|
+
}
|
|
322
|
+
cowShedHooks = new CowShedHooks(chainId, customOptions);
|
|
323
|
+
this.hooksCache.set(chainId, cowShedHooks);
|
|
324
|
+
return cowShedHooks;
|
|
325
|
+
}
|
|
326
|
+
static getNonce() {
|
|
327
|
+
const adapter = (0, import_sdk_common2.getGlobalAdapter)();
|
|
328
|
+
return adapter.utils.formatBytes32String(Date.now().toString());
|
|
329
|
+
}
|
|
330
|
+
};
|
|
331
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
332
|
+
0 && (module.exports = {
|
|
333
|
+
COW_SHED_712_TYPES,
|
|
334
|
+
COW_SHED_PROXY_INIT_CODE,
|
|
335
|
+
CowShedHooks,
|
|
336
|
+
CowShedSdk
|
|
337
|
+
});
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,318 @@
|
|
|
1
|
+
// src/contracts/CoWShedHooks.ts
|
|
2
|
+
import { ecdsaSignTypedData } from "@cowprotocol/sdk-contracts-ts";
|
|
3
|
+
import { COW_SHED_FACTORY, COW_SHED_IMPLEMENTATION } from "@cowprotocol/sdk-config";
|
|
4
|
+
import {
|
|
5
|
+
getGlobalAdapter,
|
|
6
|
+
setGlobalAdapter
|
|
7
|
+
} from "@cowprotocol/sdk-common";
|
|
8
|
+
|
|
9
|
+
// src/abi/CowShedFactoryAbi.ts
|
|
10
|
+
var CowShedFactoryAbi = [
|
|
11
|
+
{
|
|
12
|
+
inputs: [
|
|
13
|
+
{ internalType: "address", name: "impl", type: "address" },
|
|
14
|
+
{ internalType: "bytes32", name: "bName", type: "bytes32" },
|
|
15
|
+
{ internalType: "bytes32", name: "bNode", type: "bytes32" }
|
|
16
|
+
],
|
|
17
|
+
stateMutability: "nonpayable",
|
|
18
|
+
type: "constructor"
|
|
19
|
+
},
|
|
20
|
+
{ inputs: [], name: "InvalidSignature", type: "error" },
|
|
21
|
+
{ inputs: [], name: "NonceAlreadyUsed", type: "error" },
|
|
22
|
+
{ inputs: [], name: "SettingEnsRecordsFailed", type: "error" },
|
|
23
|
+
{
|
|
24
|
+
anonymous: false,
|
|
25
|
+
inputs: [
|
|
26
|
+
{ indexed: false, internalType: "address", name: "user", type: "address" },
|
|
27
|
+
{ indexed: false, internalType: "address", name: "shed", type: "address" }
|
|
28
|
+
],
|
|
29
|
+
name: "COWShedBuilt",
|
|
30
|
+
type: "event"
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
inputs: [{ internalType: "bytes32", name: "node", type: "bytes32" }],
|
|
34
|
+
name: "addr",
|
|
35
|
+
outputs: [{ internalType: "address", name: "", type: "address" }],
|
|
36
|
+
stateMutability: "view",
|
|
37
|
+
type: "function"
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
inputs: [],
|
|
41
|
+
name: "baseName",
|
|
42
|
+
outputs: [{ internalType: "string", name: "", type: "string" }],
|
|
43
|
+
stateMutability: "view",
|
|
44
|
+
type: "function"
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
inputs: [],
|
|
48
|
+
name: "baseNode",
|
|
49
|
+
outputs: [{ internalType: "bytes32", name: "", type: "bytes32" }],
|
|
50
|
+
stateMutability: "view",
|
|
51
|
+
type: "function"
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
inputs: [
|
|
55
|
+
{
|
|
56
|
+
components: [
|
|
57
|
+
{ internalType: "address", name: "target", type: "address" },
|
|
58
|
+
{ internalType: "uint256", name: "value", type: "uint256" },
|
|
59
|
+
{ internalType: "bytes", name: "callData", type: "bytes" },
|
|
60
|
+
{ internalType: "bool", name: "allowFailure", type: "bool" },
|
|
61
|
+
{ internalType: "bool", name: "isDelegateCall", type: "bool" }
|
|
62
|
+
],
|
|
63
|
+
internalType: "struct Call[]",
|
|
64
|
+
name: "calls",
|
|
65
|
+
type: "tuple[]"
|
|
66
|
+
},
|
|
67
|
+
{ internalType: "bytes32", name: "nonce", type: "bytes32" },
|
|
68
|
+
{ internalType: "uint256", name: "deadline", type: "uint256" },
|
|
69
|
+
{ internalType: "address", name: "user", type: "address" },
|
|
70
|
+
{ internalType: "bytes", name: "signature", type: "bytes" }
|
|
71
|
+
],
|
|
72
|
+
name: "executeHooks",
|
|
73
|
+
outputs: [],
|
|
74
|
+
stateMutability: "nonpayable",
|
|
75
|
+
type: "function"
|
|
76
|
+
},
|
|
77
|
+
{
|
|
78
|
+
inputs: [{ internalType: "bytes32", name: "", type: "bytes32" }],
|
|
79
|
+
name: "forwardResolutionNodeToAddress",
|
|
80
|
+
outputs: [{ internalType: "address", name: "", type: "address" }],
|
|
81
|
+
stateMutability: "view",
|
|
82
|
+
type: "function"
|
|
83
|
+
},
|
|
84
|
+
{
|
|
85
|
+
inputs: [],
|
|
86
|
+
name: "implementation",
|
|
87
|
+
outputs: [{ internalType: "address", name: "", type: "address" }],
|
|
88
|
+
stateMutability: "view",
|
|
89
|
+
type: "function"
|
|
90
|
+
},
|
|
91
|
+
{
|
|
92
|
+
inputs: [{ internalType: "address", name: "user", type: "address" }],
|
|
93
|
+
name: "initializeEns",
|
|
94
|
+
outputs: [],
|
|
95
|
+
stateMutability: "nonpayable",
|
|
96
|
+
type: "function"
|
|
97
|
+
},
|
|
98
|
+
{
|
|
99
|
+
inputs: [
|
|
100
|
+
{ internalType: "address", name: "user", type: "address" },
|
|
101
|
+
{ internalType: "bool", name: "withEns", type: "bool" }
|
|
102
|
+
],
|
|
103
|
+
name: "initializeProxy",
|
|
104
|
+
outputs: [],
|
|
105
|
+
stateMutability: "nonpayable",
|
|
106
|
+
type: "function"
|
|
107
|
+
},
|
|
108
|
+
{
|
|
109
|
+
inputs: [{ internalType: "bytes32", name: "node", type: "bytes32" }],
|
|
110
|
+
name: "name",
|
|
111
|
+
outputs: [{ internalType: "string", name: "", type: "string" }],
|
|
112
|
+
stateMutability: "view",
|
|
113
|
+
type: "function"
|
|
114
|
+
},
|
|
115
|
+
{
|
|
116
|
+
inputs: [{ internalType: "address", name: "", type: "address" }],
|
|
117
|
+
name: "ownerOf",
|
|
118
|
+
outputs: [{ internalType: "address", name: "", type: "address" }],
|
|
119
|
+
stateMutability: "view",
|
|
120
|
+
type: "function"
|
|
121
|
+
},
|
|
122
|
+
{
|
|
123
|
+
inputs: [{ internalType: "address", name: "who", type: "address" }],
|
|
124
|
+
name: "proxyOf",
|
|
125
|
+
outputs: [{ internalType: "address", name: "", type: "address" }],
|
|
126
|
+
stateMutability: "view",
|
|
127
|
+
type: "function"
|
|
128
|
+
},
|
|
129
|
+
{
|
|
130
|
+
inputs: [{ internalType: "bytes32", name: "", type: "bytes32" }],
|
|
131
|
+
name: "reverseResolutionNodeToAddress",
|
|
132
|
+
outputs: [{ internalType: "address", name: "", type: "address" }],
|
|
133
|
+
stateMutability: "view",
|
|
134
|
+
type: "function"
|
|
135
|
+
},
|
|
136
|
+
{
|
|
137
|
+
inputs: [{ internalType: "bytes4", name: "interfaceId", type: "bytes4" }],
|
|
138
|
+
name: "supportsInterface",
|
|
139
|
+
outputs: [{ internalType: "bool", name: "", type: "bool" }],
|
|
140
|
+
stateMutability: "pure",
|
|
141
|
+
type: "function"
|
|
142
|
+
}
|
|
143
|
+
];
|
|
144
|
+
|
|
145
|
+
// src/contracts/CoWShedHooks.ts
|
|
146
|
+
var COW_SHED_PROXY_INIT_CODE = "0x60a034608e57601f61037138819003918201601f19168301916001600160401b038311848410176093578084926040948552833981010312608e57604b602060458360a9565b920160a9565b6080527f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc556040516102b490816100bd8239608051818181608f01526101720152f35b600080fd5b634e487b7160e01b600052604160045260246000fd5b51906001600160a01b0382168203608e5756fe60806040526004361015610018575b3661019457610194565b6000803560e01c908163025b22bc1461003b575063f851a4400361000e5761010d565b3461010a5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261010a5773ffffffffffffffffffffffffffffffffffffffff60043581811691828203610106577f0000000000000000000000000000000000000000000000000000000000000000163314600014610101577f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc557fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b8280a280f35b61023d565b8380fd5b80fd5b346101645760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610164576020610146610169565b73ffffffffffffffffffffffffffffffffffffffff60405191168152f35b600080fd5b333003610101577f000000000000000000000000000000000000000000000000000000000000000090565b60ff7f68df44b1011761f481358c0f49a711192727fb02c377d697bcb0ea8ff8393ac0541615806101ef575b1561023d5760046040517ff92ee8a9000000000000000000000000000000000000000000000000000000008152fd5b507f400ada75000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000006000351614156101c0565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc546000808092368280378136915af43d82803e1561027a573d90f35b3d90fdfea2646970667358221220c7c26ff3040b96a28e96d6d27b743972943aeaef81cc821544c5fe1e24f9b17264736f6c63430008190033";
|
|
147
|
+
var COW_SHED_712_TYPES = {
|
|
148
|
+
ExecuteHooks: [
|
|
149
|
+
{ type: "Call[]", name: "calls" },
|
|
150
|
+
{ type: "bytes32", name: "nonce" },
|
|
151
|
+
{ type: "uint256", name: "deadline" }
|
|
152
|
+
],
|
|
153
|
+
Call: [
|
|
154
|
+
{ type: "address", name: "target" },
|
|
155
|
+
{ type: "uint256", name: "value" },
|
|
156
|
+
{ type: "bytes", name: "callData" },
|
|
157
|
+
{ type: "bool", name: "allowFailure" },
|
|
158
|
+
{ type: "bool", name: "isDelegateCall" }
|
|
159
|
+
]
|
|
160
|
+
};
|
|
161
|
+
var CowShedHooks = class {
|
|
162
|
+
constructor(chainId, customOptions, adapter) {
|
|
163
|
+
this.chainId = chainId;
|
|
164
|
+
this.customOptions = customOptions;
|
|
165
|
+
if (adapter) {
|
|
166
|
+
setGlobalAdapter(adapter);
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
proxyOf(user) {
|
|
170
|
+
const adapter = getGlobalAdapter();
|
|
171
|
+
const salt = adapter.utils.encodeAbi(["address"], [user]);
|
|
172
|
+
const initCodeHash = adapter.utils.solidityKeccak256(
|
|
173
|
+
["bytes", "bytes"],
|
|
174
|
+
[
|
|
175
|
+
this.proxyCreationCode(),
|
|
176
|
+
adapter.utils.encodeAbi(["address", "address"], [this.getImplementationAddress(), user])
|
|
177
|
+
]
|
|
178
|
+
);
|
|
179
|
+
return adapter.utils.getCreate2Address(this.getFactoryAddress(), salt, initCodeHash);
|
|
180
|
+
}
|
|
181
|
+
encodeExecuteHooksForFactory(calls, nonce, deadline, ownerAddress, signature) {
|
|
182
|
+
const adapter = getGlobalAdapter();
|
|
183
|
+
return adapter.utils.encodeFunction(CowShedFactoryAbi, "executeHooks", [
|
|
184
|
+
calls,
|
|
185
|
+
nonce,
|
|
186
|
+
deadline,
|
|
187
|
+
ownerAddress,
|
|
188
|
+
signature
|
|
189
|
+
]);
|
|
190
|
+
}
|
|
191
|
+
async signCalls(calls, nonce, deadline, signingScheme, owner) {
|
|
192
|
+
const adapter = getGlobalAdapter();
|
|
193
|
+
const signer = owner ? adapter.createSigner(owner) : adapter.signer;
|
|
194
|
+
const user = await signer.getAddress();
|
|
195
|
+
const proxy = this.proxyOf(user);
|
|
196
|
+
const { domain, types, message } = this.infoToSign(calls, nonce, deadline, proxy);
|
|
197
|
+
return await ecdsaSignTypedData(signingScheme, domain, types, message, signer);
|
|
198
|
+
}
|
|
199
|
+
infoToSign(calls, nonce, deadline, proxy) {
|
|
200
|
+
const message = {
|
|
201
|
+
calls: calls.map((call) => ({
|
|
202
|
+
target: call.target.toLowerCase(),
|
|
203
|
+
value: call.value,
|
|
204
|
+
callData: call.callData,
|
|
205
|
+
allowFailure: call.allowFailure,
|
|
206
|
+
isDelegateCall: call.isDelegateCall
|
|
207
|
+
})),
|
|
208
|
+
nonce,
|
|
209
|
+
deadline: deadline.toString()
|
|
210
|
+
};
|
|
211
|
+
return { domain: this.getDomain(proxy), types: COW_SHED_712_TYPES, message };
|
|
212
|
+
}
|
|
213
|
+
getDomain(proxy) {
|
|
214
|
+
return {
|
|
215
|
+
name: "COWShed",
|
|
216
|
+
version: "1.0.0",
|
|
217
|
+
chainId: typeof this.chainId === "bigint" ? Number(this.chainId) : this.chainId,
|
|
218
|
+
verifyingContract: proxy.toLowerCase()
|
|
219
|
+
};
|
|
220
|
+
}
|
|
221
|
+
proxyCreationCode() {
|
|
222
|
+
return this.customOptions?.proxyCreationCode ?? COW_SHED_PROXY_INIT_CODE;
|
|
223
|
+
}
|
|
224
|
+
getFactoryAddress() {
|
|
225
|
+
return this.customOptions?.factoryAddress ?? COW_SHED_FACTORY;
|
|
226
|
+
}
|
|
227
|
+
getImplementationAddress() {
|
|
228
|
+
return this.customOptions?.implementationAddress ?? COW_SHED_IMPLEMENTATION;
|
|
229
|
+
}
|
|
230
|
+
};
|
|
231
|
+
|
|
232
|
+
// src/CowShedSdk.ts
|
|
233
|
+
import {
|
|
234
|
+
ContractsSigningScheme as SigningScheme
|
|
235
|
+
} from "@cowprotocol/sdk-contracts-ts";
|
|
236
|
+
import {
|
|
237
|
+
log,
|
|
238
|
+
MAX_UINT256 as NON_EXPIRING_DEADLINE,
|
|
239
|
+
jsonWithBigintReplacer,
|
|
240
|
+
getGlobalAdapter as getGlobalAdapter2,
|
|
241
|
+
setGlobalAdapter as setGlobalAdapter2
|
|
242
|
+
} from "@cowprotocol/sdk-common";
|
|
243
|
+
var CowShedSdk = class _CowShedSdk {
|
|
244
|
+
constructor(adapter, factoryOptions) {
|
|
245
|
+
this.factoryOptions = factoryOptions;
|
|
246
|
+
if (adapter) {
|
|
247
|
+
setGlobalAdapter2(adapter);
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
hooksCache = /* @__PURE__ */ new Map();
|
|
251
|
+
getCowShedAccount(chainId, ownerAddress) {
|
|
252
|
+
const cowShedHooks = this.getCowShedHooks(chainId, this.factoryOptions);
|
|
253
|
+
return cowShedHooks.proxyOf(ownerAddress);
|
|
254
|
+
}
|
|
255
|
+
/**
|
|
256
|
+
* Encodes multiple calls into a single pre-authorized call to the cow-shed factory.
|
|
257
|
+
*
|
|
258
|
+
* This single call will create the cow-shed account if it doesn't exist yet, then will execute the calls.
|
|
259
|
+
*
|
|
260
|
+
* @returns pre-authorized multicall details
|
|
261
|
+
*/
|
|
262
|
+
async signCalls({
|
|
263
|
+
calls,
|
|
264
|
+
signer: signerParam,
|
|
265
|
+
chainId,
|
|
266
|
+
nonce = _CowShedSdk.getNonce(),
|
|
267
|
+
deadline = NON_EXPIRING_DEADLINE,
|
|
268
|
+
defaultGasLimit,
|
|
269
|
+
signingScheme = SigningScheme.EIP712
|
|
270
|
+
}) {
|
|
271
|
+
const cowShedHooks = this.getCowShedHooks(chainId);
|
|
272
|
+
const adapter = getGlobalAdapter2();
|
|
273
|
+
const signer = signerParam ? adapter.createSigner(signerParam) : adapter.signer;
|
|
274
|
+
const ownerAddress = await signer.getAddress();
|
|
275
|
+
const cowShedAccount = cowShedHooks.proxyOf(ownerAddress);
|
|
276
|
+
const signature = await cowShedHooks.signCalls(calls, nonce, deadline, signingScheme, signer);
|
|
277
|
+
const callData = cowShedHooks.encodeExecuteHooksForFactory(calls, nonce, deadline, ownerAddress, signature);
|
|
278
|
+
const cowShedFactoryAddress = cowShedHooks.getFactoryAddress();
|
|
279
|
+
const factoryCall = {
|
|
280
|
+
to: cowShedFactoryAddress,
|
|
281
|
+
data: callData,
|
|
282
|
+
value: BigInt(0)
|
|
283
|
+
};
|
|
284
|
+
const gasEstimate = await signer.estimateGas(factoryCall).catch((error) => {
|
|
285
|
+
const factoryCallString = JSON.stringify(factoryCall, jsonWithBigintReplacer, 2);
|
|
286
|
+
const errorMessage = `Error estimating gas for the cow-shed call: ${factoryCallString}. Review the factory call`;
|
|
287
|
+
if (defaultGasLimit) {
|
|
288
|
+
log(`${errorMessage}, using the default gas limit.`);
|
|
289
|
+
return defaultGasLimit;
|
|
290
|
+
}
|
|
291
|
+
throw new Error(`${errorMessage}, or provide the defaultGasLimit parameter.`, { cause: error });
|
|
292
|
+
});
|
|
293
|
+
return {
|
|
294
|
+
cowShedAccount,
|
|
295
|
+
signedMulticall: factoryCall,
|
|
296
|
+
gasLimit: gasEstimate
|
|
297
|
+
};
|
|
298
|
+
}
|
|
299
|
+
getCowShedHooks(chainId, customOptions) {
|
|
300
|
+
let cowShedHooks = this.hooksCache.get(chainId);
|
|
301
|
+
if (cowShedHooks) {
|
|
302
|
+
return cowShedHooks;
|
|
303
|
+
}
|
|
304
|
+
cowShedHooks = new CowShedHooks(chainId, customOptions);
|
|
305
|
+
this.hooksCache.set(chainId, cowShedHooks);
|
|
306
|
+
return cowShedHooks;
|
|
307
|
+
}
|
|
308
|
+
static getNonce() {
|
|
309
|
+
const adapter = getGlobalAdapter2();
|
|
310
|
+
return adapter.utils.formatBytes32String(Date.now().toString());
|
|
311
|
+
}
|
|
312
|
+
};
|
|
313
|
+
export {
|
|
314
|
+
COW_SHED_712_TYPES,
|
|
315
|
+
COW_SHED_PROXY_INIT_CODE,
|
|
316
|
+
CowShedHooks,
|
|
317
|
+
CowShedSdk
|
|
318
|
+
};
|
package/package.json
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@cowprotocol/sdk-cow-shed",
|
|
3
|
+
"version": "0.1.0-monorepo.0",
|
|
4
|
+
"description": "CowProtocol Cow Shed package",
|
|
5
|
+
"main": "./dist/index.js",
|
|
6
|
+
"module": "./dist/index.mjs",
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
|
+
"sideEffects": false,
|
|
9
|
+
"license": "MIT",
|
|
10
|
+
"files": [
|
|
11
|
+
"dist/**"
|
|
12
|
+
],
|
|
13
|
+
"scripts": {
|
|
14
|
+
"build": "tsup src/index.ts --format esm,cjs --dts",
|
|
15
|
+
"lint": "eslint src/**/*.ts --quiet",
|
|
16
|
+
"test": "jest",
|
|
17
|
+
"test:coverage": "jest --coverage --json --outputFile=jest.results.json && cat ./coverage/lcov.info | coveralls",
|
|
18
|
+
"test:coverage:html": "jest --silent=false --coverage --coverageReporters html",
|
|
19
|
+
"typecheck": "tsc --noEmit",
|
|
20
|
+
"clean": "rm -rf .turbo && rm -rf node_modules && rm -rf dist"
|
|
21
|
+
},
|
|
22
|
+
"dependencies": {
|
|
23
|
+
"@cowprotocol/sdk-config": "workspace:*",
|
|
24
|
+
"@cowprotocol/sdk-common": "workspace:*",
|
|
25
|
+
"@cowprotocol/sdk-contracts-ts": "workspace:*"
|
|
26
|
+
},
|
|
27
|
+
"devDependencies": {
|
|
28
|
+
"@cow-sdk/typescript-config": "workspace:*",
|
|
29
|
+
"@cowprotocol/sdk-ethers-v5-adapter": "workspace:*",
|
|
30
|
+
"@cowprotocol/sdk-ethers-v6-adapter": "workspace:*",
|
|
31
|
+
"@cowprotocol/sdk-viem-adapter": "workspace:*",
|
|
32
|
+
"@types/jest": "^29.4.0",
|
|
33
|
+
"@types/node": "^20.17.31",
|
|
34
|
+
"@types/semver-sort": "^0.0.1",
|
|
35
|
+
"@ethersproject/constants": "^5.7.0",
|
|
36
|
+
"ethers-v5": "npm:ethers@^5.7.2",
|
|
37
|
+
"ethers-v6": "npm:ethers@^6.13.7",
|
|
38
|
+
"viem": "^2.28.4",
|
|
39
|
+
"jest": "^29.7.0",
|
|
40
|
+
"jest-fetch-mock": "^3.0.3",
|
|
41
|
+
"ts-jest": "^29.0.0",
|
|
42
|
+
"tsup": "^7.2.0",
|
|
43
|
+
"tsx": "^4.19.4",
|
|
44
|
+
"typescript": "^5.2.2"
|
|
45
|
+
}
|
|
46
|
+
}
|