Skip to content

Commit

Permalink
Implement new payload packet schema
Browse files Browse the repository at this point in the history
  • Loading branch information
Agusx1211 committed Sep 8, 2023
1 parent d5e01b1 commit 74e5c94
Show file tree
Hide file tree
Showing 4 changed files with 299 additions and 68 deletions.
21 changes: 21 additions & 0 deletions packages/waas/src/payloads/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { ethers } from "ethers"

export type BasePacket = {
code: string
}

export type Signature = {
session: string,
signature: string
}

export type Payload<T extends BasePacket> = {
version: string,
packet: T,
signatures: Signature[]
}

export function signPacket(signer: ethers.Signer, packed: BasePacket): Promise<string> {
const encoded = ethers.utils.toUtf8Bytes(JSON.stringify(packed, null, 0))
return signer.signMessage(encoded)
}
27 changes: 13 additions & 14 deletions packages/waas/src/payloads/session.ts
Original file line number Diff line number Diff line change
@@ -1,24 +1,21 @@

import { ethers } from 'ethers'
import { BasePacket } from '.'

export type SessionPayload = {
export type SessionPacket = BasePacket & {
code: 'openSession'
signer: string;
proof: {
email?: string;
idToken?: string;
}
}

export type SessionReceipt = {
signer: string;
wallet: string;
}

export function isSessionPayload(payload: any): payload is SessionPayload {
return (
typeof payload === 'object' &&
typeof payload.signer === 'string' &&
typeof payload.idToken === 'string' &&
ethers.utils.isAddress(payload.signer)
)
}

export function isSessionReceipt(receipt: any): receipt is SessionReceipt {
return (
typeof receipt === 'object' &&
Expand All @@ -29,13 +26,15 @@ export function isSessionReceipt(receipt: any): receipt is SessionReceipt {
)
}

export async function openSession(): Promise<{ payload: SessionPayload, signer: ethers.Wallet }> {
export async function openSession(): Promise<{ packet: SessionPacket, signer: ethers.Wallet }> {
const signer = ethers.Wallet.createRandom()

return {
signer,
payload: {
signer: signer.address
}
packet: {
code: 'openSession',
signer: signer.address,
proof: {} // Will be added server-side
},
}
}
192 changes: 156 additions & 36 deletions packages/waas/src/payloads/wallet.ts
Original file line number Diff line number Diff line change
@@ -1,59 +1,179 @@
import { ethers } from "ethers"
import { BasePacket } from "."

export type TransactionsPayload = {
export type TransactionsPacket = BasePacket & {
wallet: string;
chainId: number;

transaction: ethers.providers.TransactionRequest[];
transactions: TransactionSubpacket[]
}

signer: {
address: string;
signature: string;
}
export type TransactionSubpacket =
RawTransactionSubpacket |
SendERC20Subpacket |
SendERC721Subpacket |
SendERC1155Subpacket


export type RawTransactionSubpacket = {
type: 'transaction',
to: string,
value: string,
data: string
}

export function hashTransactionsPayload(wallet: string, transactions: ethers.providers.TransactionRequest[], chainId: number): string {
const txHashes = transactions.map(transaction =>
ethers.utils.keccak256(
ethers.utils.defaultAbiCoder.encode(
['address', 'uint256', 'bytes', 'uint256'],
[transaction.to, transaction.value, transaction.data]
)
)
)
export type SendERC20Subpacket = {
type: 'erc20send',
token: string,
to: string,
value: string
}

const preimage = ethers.utils.keccak256(
ethers.utils.defaultAbiCoder.encode(
['bytes32[]'],
[[
ethers.utils.defaultAbiCoder.encode(['uint256'], [chainId]),
ethers.utils.defaultAbiCoder.encode(['address'], [wallet]),
...txHashes
]]
)
)
export type SendERC721Subpacket = {
type: 'erc721send',
token: string,
to: string,
id: string,
safe?: boolean,
data?: string
}

return preimage
export type SendERC1155Subpacket = {
type: 'erc1155send',
token: string,
to: string,
vals: {
id: string,
amount: string
}[],
data?: string
}

export async function sendTransactions(
signer: ethers.Wallet,
export function sendTransactions(
wallet: string,
transactions: ethers.providers.TransactionRequest[],
chainId: number
): Promise<TransactionsPayload> {
const hash = hashTransactionsPayload(wallet, transactions, chainId)
const signature = await signer.signMessage(ethers.utils.arrayify(hash))
): TransactionsPacket {
return {
code: 'sendTransactions',
wallet,
chainId,
transactions: transactions.map(tx => {
if (!tx.to || tx.to === ethers.constants.AddressZero) {
throw new Error('Contract creation not supported')
}

return {
type: 'transaction',
to: tx.to,
value: ethers.BigNumber.from(tx.value || 0).toHexString(),
data: ethers.utils.hexlify(tx.data || [])
}
})
}
}

export function sendERC20(
wallet: string,
token: string,
to: string,
value: ethers.BigNumberish,
chainId: number
): TransactionsPacket {
return {
code: 'sendTransactions',
wallet,
chainId,
transactions: [
{
type: 'erc20send',
token,
to,
value: ethers.BigNumber.from(value).toString()
}
]
}
}

transaction: transactions,
export function sendERC721(
wallet: string,
token: string,
to: string,
id: string,
chainId: number,
safe?: boolean,
data?: string
): TransactionsPacket {
return {
code: 'sendTransactions',
wallet,
chainId,
transactions: [
{
type: 'erc721send',
token,
to,
id,
safe,
data
}
]
}
}

export function sendERC1155(
wallet: string,
token: string,
to: string,
vals: {
id: string,
amount: ethers.BigNumberish
}[],
chainId: number,
data?: string
): TransactionsPacket {
return {
code: 'sendTransactions',
wallet,
chainId,
transactions: [
{
type: 'erc1155send',
token,
to,
vals: vals.map(v => ({
id: v.id,
amount: ethers.BigNumber.from(v.amount).toString()
})),
data
}
]
}
}

signer: {
address: signer.address,
signature
}
export function combinePackets(
packets: TransactionsPacket[]
): TransactionsPacket {
if (packets.length === 0) {
throw new Error('No packets provided')
}

// Ensure that all packets are for the same network and wallet
const chainId = packets[0].chainId
const wallet = packets[0].wallet

if (!packets.every(p => p.chainId === chainId)) {
throw new Error('All packets must have the same chainId')
}

if (!packets.every(p => p.wallet === wallet)) {
throw new Error('All packets must have the same wallet')
}

return {
code: 'sendTransactions',
chainId,
wallet,
transactions: packets.reduce((acc, p) => acc.concat(p.transactions), [] as TransactionSubpacket[])
}
}
Loading

0 comments on commit 74e5c94

Please sign in to comment.