-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #6 from argentlabs/fix/offchain-sessions-v5
fix: support offchain sessions for v5
- Loading branch information
Showing
5 changed files
with
250 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,6 @@ | ||
export * from "./utils" | ||
export * from "./offchainSessionUtils" | ||
export { SessionAccount } from "./account" | ||
export { OffchainSessionAccountV5 } from "./offchainSessionAccountV5" | ||
export { OffchainSessionAccount } from "./offchainSessionAccount" | ||
export { OffchainSessionAccount as default } from "./offchainSessionAccount" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,159 @@ | ||
import { | ||
Abi, | ||
Account, | ||
AccountInterface, | ||
Call, | ||
CallData, | ||
InvocationsDetails, | ||
InvocationsSignerDetails, | ||
InvokeFunctionResponse, | ||
ProviderInterface, | ||
ProviderOptions, | ||
Signature, | ||
SignerInterface, | ||
TransactionType, | ||
num, | ||
stark, | ||
} from "starknet" | ||
import { ensureArray } from "./ensureArray" | ||
import { OffchainSessionCall } from "./interface" | ||
|
||
const OFFCHAIN_SESSION_ENTRYPOINT = "use_offchain_session" | ||
|
||
export class OffchainSessionAccountV5 | ||
extends Account | ||
implements AccountInterface | ||
{ | ||
constructor( | ||
providerOrOptions: ProviderOptions | ProviderInterface, | ||
address: string, | ||
pkOrSigner: Uint8Array | string | SignerInterface, | ||
public sessionSignature: Signature, | ||
public account: AccountInterface, | ||
) { | ||
super(providerOrOptions, address, pkOrSigner, "1") | ||
} | ||
|
||
private async sessionToCall( | ||
dappSignature: Signature, | ||
): Promise<OffchainSessionCall> { | ||
const signature = stark.formatSignature(this.sessionSignature) | ||
const formattedDappSignature = stark.formatSignature(dappSignature) | ||
|
||
return { | ||
contractAddress: this.address, | ||
entrypoint: OFFCHAIN_SESSION_ENTRYPOINT, | ||
calldata: CallData.compile({ | ||
signer: await this.signer.getPubKey(), | ||
token1: formattedDappSignature[0], | ||
token2: formattedDappSignature[1], | ||
// owner | ||
token3: signature[0], | ||
token4: signature[1], | ||
// cosigner | ||
token5: signature[2], | ||
token6: signature[3], | ||
}), | ||
} | ||
} | ||
|
||
private async extendCallsBySession( | ||
calls: Call[], | ||
dappSignature: Signature, | ||
): Promise<OffchainSessionCall[]> { | ||
const sessionCall = await this.sessionToCall(dappSignature) | ||
return [sessionCall, ...calls] | ||
} | ||
|
||
/** | ||
* Invoke execute function in account contract | ||
* | ||
* [Reference](https://github.com/starkware-libs/cairo-lang/blob/f464ec4797361b6be8989e36e02ec690e74ef285/src/starkware/starknet/services/api/gateway/gateway_client.py#L13-L17) | ||
* | ||
* @param calls - one or more calls to be executed | ||
* @param abis - one or more abis which can be used to display the calls | ||
* @param transactionsDetail - optional transaction details | ||
* @returns a confirmation of invoking a function on the starknet contract | ||
*/ | ||
public async execute( | ||
calls: Call | Call[], | ||
abis: Abi[] | undefined = undefined, | ||
transactionsDetail: InvocationsDetails = {}, | ||
): Promise<InvokeFunctionResponse> { | ||
const transactions = ensureArray(calls) | ||
|
||
const version = "0x1" as const | ||
const chainId = await this.getChainId() | ||
|
||
const nonce = num.toHex(transactionsDetail.nonce ?? (await this.getNonce())) | ||
|
||
let maxFee = transactionsDetail.maxFee | ||
|
||
if (!maxFee) { | ||
try { | ||
const sim = await this.simulateTransaction( | ||
[ | ||
{ | ||
type: TransactionType.INVOKE, | ||
payload: calls, | ||
}, | ||
], | ||
{ | ||
skipValidate: true, | ||
nonce, | ||
}, | ||
) | ||
|
||
const [estimation] = sim | ||
const { fee_estimation } = estimation | ||
const overall_fee = fee_estimation.overall_fee | ||
maxFee = estimation.suggestedMaxFee ?? overall_fee | ||
} catch (e) { | ||
// fallback | ||
maxFee = ( | ||
await this.getSuggestedFee( | ||
{ | ||
type: TransactionType.INVOKE, | ||
payload: calls, | ||
}, | ||
{ | ||
skipValidate: true, | ||
nonce, | ||
}, | ||
) | ||
).suggestedMaxFee | ||
} | ||
} | ||
|
||
const signerDetails: InvocationsSignerDetails = { | ||
walletAddress: this.account.address, | ||
nonce, | ||
maxFee, | ||
version, | ||
chainId, | ||
cairoVersion: this.cairoVersion ?? "1", | ||
} | ||
|
||
const dappSignature = await this.signer.signTransaction( | ||
transactions, | ||
signerDetails, | ||
abis, | ||
) | ||
|
||
const transactionsWithSession = await this.extendCallsBySession( | ||
transactions, | ||
dappSignature, | ||
) | ||
|
||
/* | ||
need to use the same values for transactionDetails (nonce, maxFee, version) | ||
otherwise the cosign would fail most of the times | ||
since maxFee could change in a very short time if calculated in both this package and in webwallet | ||
*/ | ||
return this.account?.execute(transactionsWithSession, abis, { | ||
nonce, | ||
maxFee: maxFee.toString(), | ||
version, | ||
}) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters