11import { ethers } from 'ethers' ;
22
3- import {
4- // createSiweMessageWithRecaps,
5- // generateAuthSig,
6- LitActionResource ,
7- // LitPKPResource,
8- } from '@lit-protocol/auth-helpers' ;
9- import {
10- LIT_ABILITY ,
11- LIT_EVM_CHAINS ,
12- LIT_RPC ,
13- LIT_NETWORK ,
14- } from '@lit-protocol/constants' ;
3+ import { LitActionResource } from '@lit-protocol/auth-helpers' ;
4+ import { LIT_ABILITY , LIT_RPC } from '@lit-protocol/constants' ;
155import { LitContracts } from '@lit-protocol/contracts-sdk' ;
166import { EthWalletProvider } from '@lit-protocol/lit-auth-client' ;
177import { LitNodeClient } from '@lit-protocol/lit-node-client' ;
@@ -23,25 +13,15 @@ import {
2313 Listener ,
2414 TimerListener ,
2515} from './listeners' ;
16+ import { signWithLitActionCode } from './litActions' ;
2617import { State , StateParams } from './states' ;
2718import { Check , Transition } from './transitions' ;
2819import { getChain } from './utils/chain' ;
2920import { getBalanceTransitionCheck , getERC20Balance } from './utils/erc20' ;
3021
3122import type {
32- Address ,
33- BalanceTransitionDefinition ,
34- BaseBalanceTransitionDefinition ,
3523 BaseStateMachineParams ,
36- ERC20BalanceTransitionDefinition ,
37- EvmContractEventTransitionDefinition ,
38- IntervalTransitionDefinition ,
39- NativeBalanceTransitionDefinition ,
40- OnEvmChainEvent ,
41- StateDefinition ,
4224 StateMachineDefinition ,
43- TimerTransitionDefinition ,
44- TransitionDefinition ,
4525 TransitionParams ,
4626} from './types' ;
4727
@@ -51,11 +31,58 @@ const ethPrivateKey = process.env['ETHEREUM_PRIVATE_KEY'];
5131if ( ! ethPrivateKey ) {
5232 throw new Error ( 'ethPrivateKey not defined' ) ;
5333}
54- const yellowstoneSigner = new ethers . Wallet (
34+ const yellowstoneLitSigner = new ethers . Wallet (
5535 ethPrivateKey ,
5636 new ethers . providers . JsonRpcProvider ( LIT_RPC . CHRONICLE_YELLOWSTONE )
5737) ;
5838
39+ // TODO improve and move
40+ interface ExecuteLitAction {
41+ litNodeClient : LitNodeClient ;
42+ pkpPublicKey : string ;
43+ machineSigner : ethers . Wallet ;
44+ ipfsId ?: string ;
45+ code : string ;
46+ jsParams : Record < string , any > ;
47+ }
48+
49+ async function executeLitAction ( {
50+ litNodeClient,
51+ pkpPublicKey,
52+ machineSigner,
53+ ipfsId,
54+ code,
55+ jsParams,
56+ } : ExecuteLitAction ) {
57+ const pkpSessionSigs = await litNodeClient . getPkpSessionSigs ( {
58+ pkpPublicKey,
59+ capabilityAuthSigs : [ ] ,
60+ authMethods : [
61+ await EthWalletProvider . authenticate ( {
62+ signer : machineSigner ,
63+ litNodeClient : litNodeClient ,
64+ expiration : new Date ( Date . now ( ) + 1000 * 60 * 10 ) . toISOString ( ) , // 10 minutes
65+ } ) ,
66+ ] ,
67+ resourceAbilityRequests : [
68+ {
69+ resource : new LitActionResource ( '*' ) ,
70+ ability : LIT_ABILITY . LitActionExecution ,
71+ } ,
72+ ] ,
73+ } ) ;
74+
75+ // Run a LitAction
76+ const executeJsResponse = await litNodeClient . executeJs ( {
77+ ipfsId,
78+ code,
79+ jsParams,
80+ sessionSigs : pkpSessionSigs ,
81+ } ) ;
82+
83+ return executeJsResponse ;
84+ }
85+
5986/**
6087 * A StateMachine class that manages states and transitions between them.
6188 */
@@ -83,6 +110,7 @@ export class StateMachine {
83110 static fromDefinition ( machineConfig : StateMachineDefinition ) : StateMachine {
84111 const { litNodeClient, litContracts = { } } = machineConfig ;
85112
113+ // Create litNodeClient and litContracts instances
86114 const litNodeClientInstance =
87115 'connect' in litNodeClient
88116 ? litNodeClient
@@ -91,7 +119,7 @@ export class StateMachine {
91119 'connect' in litContracts
92120 ? litContracts
93121 : new LitContracts ( {
94- signer : yellowstoneSigner ,
122+ signer : yellowstoneLitSigner ,
95123 ...litContracts ,
96124 } ) ;
97125
@@ -110,17 +138,19 @@ export class StateMachine {
110138 } ) ;
111139
112140 machineConfig . states . forEach ( ( state ) => {
113- const { litAction } = state ;
141+ const { litAction, transaction } = state ;
114142
115143 const stateConfig : StateParams = {
116144 key : state . key ,
117145 } ;
118146
147+ const onEnterFunctions = [ ] as ( ( ) => Promise < void > ) [ ] ;
148+
119149 if ( litAction ) {
120150 let pkpPublicKey : string = litAction . pkpPublicKey ;
121151
122- stateConfig . onEnter = async ( ) => {
123- const yellowstoneSigner = new ethers . Wallet (
152+ onEnterFunctions . push ( async ( ) => {
153+ const yellowstoneMachineSigner = new ethers . Wallet (
124154 litAction . pkpOwnerKey ,
125155 new ethers . providers . JsonRpcProvider ( LIT_RPC . CHRONICLE_YELLOWSTONE )
126156 ) ;
@@ -134,37 +164,99 @@ export class StateMachine {
134164 console . log ( `Minted PKP: ${ pkp } ` ) ;
135165 }
136166
137- const pkpSessionSigs = await litNodeClientInstance . getPkpSessionSigs ( {
167+ const litActionResponse = await executeLitAction ( {
168+ litNodeClient : litNodeClientInstance ,
138169 pkpPublicKey,
139- capabilityAuthSigs : [ ] ,
140- authMethods : [
141- await EthWalletProvider . authenticate ( {
142- signer : yellowstoneSigner ,
143- litNodeClient : litNodeClientInstance ,
144- expiration : new Date ( Date . now ( ) + 1000 * 60 * 10 ) . toISOString ( ) , // 10 minutes
145- } ) ,
146- ] ,
147- resourceAbilityRequests : [
148- {
149- resource : new LitActionResource ( '*' ) ,
150- ability : LIT_ABILITY . LitActionExecution ,
151- } ,
152- ] ,
153- } ) ;
154-
155- // Run a LitAction
156- const executeJsResponse = await litNodeClientInstance . executeJs ( {
157- sessionSigs : pkpSessionSigs ,
170+ machineSigner : yellowstoneMachineSigner ,
158171 ipfsId : litAction . ipfsId ,
159172 code : litAction . code ,
160173 jsParams : litAction . jsParams ,
161174 } ) ;
162175
163- // TODO send user this result with a webhook maybe
164- console . log ( `============ executeJsResponse:` , executeJsResponse ) ;
165- } ;
176+ // TODO send user this result with a webhook and log
177+ console . log ( `============ litActionResponse:` , litActionResponse ) ;
178+ } ) ;
179+ }
180+
181+ if ( transaction ) {
182+ onEnterFunctions . push ( async ( ) => {
183+ const yellowstoneMachineSigner = new ethers . Wallet (
184+ transaction . pkpOwnerKey ,
185+ new ethers . providers . JsonRpcProvider ( LIT_RPC . CHRONICLE_YELLOWSTONE )
186+ ) ;
187+
188+ const chain = getChain ( transaction ) ;
189+ const chainProvider = new ethers . providers . JsonRpcProvider (
190+ chain . rpcUrls [ 0 ] ,
191+ chain . chainId
192+ ) ;
193+
194+ const contract = new ethers . Contract (
195+ transaction . contractAddress ,
196+ transaction . contractABI ,
197+ chainProvider
198+ ) ;
199+
200+ const txData = await contract . populateTransaction [ transaction . method ] (
201+ ...( transaction . params || [ ] )
202+ ) ;
203+ const gasLimit = await chainProvider . estimateGas ( {
204+ to : transaction . contractAddress ,
205+ data : txData . data ,
206+ from : transaction . pkpEthAddress ,
207+ } ) ;
208+ const gasPrice = await chainProvider . getGasPrice ( ) ;
209+ const nonce = await chainProvider . getTransactionCount (
210+ transaction . pkpEthAddress
211+ ) ;
212+
213+ const rawTx = {
214+ chainId : chain . chainId ,
215+ data : txData . data ,
216+ gasLimit : gasLimit . toHexString ( ) ,
217+ gasPrice : gasPrice . toHexString ( ) ,
218+ nonce,
219+ to : transaction . contractAddress ,
220+ } ;
221+ const rawTxHash = ethers . utils . keccak256 (
222+ ethers . utils . serializeTransaction ( rawTx )
223+ ) ;
224+
225+ // Sign with the PKP in a LitAction
226+ const litActionResponse = await executeLitAction ( {
227+ litNodeClient : litNodeClientInstance ,
228+ pkpPublicKey : transaction . pkpPublicKey ,
229+ machineSigner : yellowstoneMachineSigner ,
230+ code : signWithLitActionCode ,
231+ jsParams : {
232+ toSign : ethers . utils . arrayify ( rawTxHash ) ,
233+ publicKey : transaction . pkpPublicKey ,
234+ sigName : 'signedTransaction' ,
235+ } ,
236+ } ) ;
237+
238+ const signature = litActionResponse . response as string ;
239+ const jsonSignature = JSON . parse ( signature ) ;
240+ jsonSignature . r = '0x' + jsonSignature . r . substring ( 2 ) ;
241+ jsonSignature . s = '0x' + jsonSignature . s ;
242+ const hexSignature = ethers . utils . joinSignature ( jsonSignature ) ;
243+
244+ const signedTx = ethers . utils . serializeTransaction (
245+ rawTx ,
246+ hexSignature
247+ ) ;
248+
249+ const receipt = await chainProvider . sendTransaction ( signedTx ) ;
250+
251+ // TODO send user this result with a webhook and log
252+ console . log ( 'Transaction Receipt:' , receipt ) ;
253+ } ) ;
166254 }
167255
256+ stateConfig . onEnter = async ( ) => {
257+ await Promise . all ( onEnterFunctions . map ( ( onEnter ) => onEnter ( ) ) ) ;
258+ } ;
259+
168260 stateMachine . addState ( stateConfig ) ;
169261 } ) ;
170262
@@ -430,6 +522,7 @@ export class StateMachine {
430522 this . isRunning && ( await this . enterState ( stateKey ) ) ;
431523 } catch ( e ) {
432524 this . currentState = undefined ;
525+ console . error ( e ) ;
433526 throw new Error ( `Could not enter state ${ stateKey } ` ) ;
434527 }
435528 }
0 commit comments