Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
spsjvc committed Dec 18, 2023
1 parent f5d1c31 commit 66b006e
Show file tree
Hide file tree
Showing 7 changed files with 270 additions and 19 deletions.
120 changes: 120 additions & 0 deletions examples/arb-owner/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
import { Chain, createPublicClient, http } from 'viem';
import { generatePrivateKey, privateKeyToAccount } from 'viem/accounts';
import { arbitrumSepolia } from 'viem/chains';
import {
createRollupPrepareConfig,
prepareChainConfig,
createRollupPrepareTransactionRequest,
createRollupPrepareTransactionReceipt,
arbOwnerPublicActions,
} from '@arbitrum/orbit-sdk';
import { generateChainId } from '@arbitrum/orbit-sdk/utils';

function sanitizePrivateKey(privateKey: string): `0x${string}` {
if (!privateKey.startsWith('0x')) {
return `0x${privateKey}`;
}

return privateKey as `0x${string}`;
}

function withFallbackPrivateKey(privateKey: string | undefined): `0x${string}` {
if (typeof privateKey === 'undefined') {
return generatePrivateKey();
}

return sanitizePrivateKey(privateKey);
}

function getBlockExplorerUrl(chain: Chain) {
return chain.blockExplorers?.default.url;
}

if (typeof process.env.DEPLOYER_PRIVATE_KEY === 'undefined') {
throw new Error(
`Please provide the "DEPLOYER_PRIVATE_KEY" environment variable`
);
}

// load or generate a random batch poster account
const batchPosterPrivateKey = withFallbackPrivateKey(
process.env.BATCH_POSTER_PRIVATE_KEY
);
const batchPoster = privateKeyToAccount(batchPosterPrivateKey).address;

// load or generate a random validator account
const validatorPrivateKey = withFallbackPrivateKey(
process.env.VALIDATOR_PRIVATE_KEY
);
const validator = privateKeyToAccount(validatorPrivateKey).address;

// set the parent chain and create a public client for it
const parentChain = arbitrumSepolia;
const publicClient = createPublicClient({
chain: parentChain,
transport: http(),
}).extend(arbOwnerPublicActions);

// load the deployer account
const deployer = privateKeyToAccount(
sanitizePrivateKey(process.env.DEPLOYER_PRIVATE_KEY)
);

async function main() {
const publicClient = createPublicClient({
chain: arbitrumSepolia,
transport: http(),
}).extend(arbOwnerPublicActions);

publicClient.arbOwnerPrepareTransactionRequest({
functionName: 'setL1BaseFeeEstimateInertia',
args: [BigInt(0)],
account: deployer.address,
});

// generate a random chain id
const chainId = generateChainId();

// create the chain config
const chainConfig = prepareChainConfig({
chainId,
arbitrum: {
InitialChainOwner: deployer.address,
DataAvailabilityCommittee: true,
},
});

// prepare the transaction for deploying the core contracts
const request = await createRollupPrepareTransactionRequest({
params: {
config: createRollupPrepareConfig({
chainId: BigInt(chainId),
owner: deployer.address,
chainConfig,
}),
batchPoster,
validators: [validator],
nativeToken: '0xf861378b543525ae0c47d33c90c954dc774ac1f9', // $ARB
},
account: deployer.address,
publicClient: publicClient,
});

// sign and send the transaction
const txHash = await publicClient.sendRawTransaction({
serializedTransaction: await deployer.signTransaction(request),
});

// get the transaction receipt after waiting for the transaction to complete
const txReceipt = createRollupPrepareTransactionReceipt(
await publicClient.waitForTransactionReceipt({ hash: txHash })
);

console.log(
`Deployed in ${getBlockExplorerUrl(parentChain)}/tx/${
txReceipt.transactionHash
}`
);
}

main();
13 changes: 13 additions & 0 deletions examples/arb-owner/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"name": "custom-fee-token",
"private": true,
"version": "0.0.0",
"type": "module",
"scripts": {
"dev": "tsc --outDir dist && node ./dist/index.js"
},
"devDependencies": {
"@types/node": "^20.9.0",
"typescript": "^5.2.2"
}
}
4 changes: 4 additions & 0 deletions examples/arb-owner/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"extends": "../tsconfig.base.json",
"include": ["./**/*"]
}
101 changes: 82 additions & 19 deletions src/arbOwnerClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,39 +4,35 @@ import {
EncodeFunctionDataParameters,
Address,
PrepareTransactionRequestReturnType,
zeroAddress,
Chain,
Transport,
Abi,
} from 'viem';

import { arbOwner } from './contracts';
import { upgradeExecutorEncodeFunctionData } from './upgradeExecutor';
import { Prettify } from './types/utils';
import { GetFunctionName, PickReadFunctionFromAbi, Prettify } from './types/utils';

type ArbOwnerFunctionDataParameters = Prettify<
type ArbOwnerEncodeFunctionDataParameters = Prettify<
Omit<EncodeFunctionDataParameters<typeof arbOwner.abi, string>, 'abi'>
>;

type X = GetFunctionName<PickReadFunctionFromAbi<typeof arbOwner.abi>>

function arbOwnerEncodeFunctionData({
functionName,
args,
}: ArbOwnerFunctionDataParameters) {
}: ArbOwnerEncodeFunctionDataParameters) {
return encodeFunctionData({
abi: arbOwner.abi,
functionName,
args,
});
}

type ArbOwnerClient = {
prepareFunctionData(
params: ArbOwnerFunctionDataParameters
): ArbOwnerClientPrepareFunctionDataResult;

prepareTransactionRequest(
params: ArbOwnerClientPrepareTransactionRequestParams
): Promise<PrepareTransactionRequestReturnType>;
};

type ArbOwnerClientPrepareTransactionRequestParams = Prettify<
ArbOwnerFunctionDataParameters & {
export type ArbOwnerPrepareTransactionRequestParameters = Prettify<
ArbOwnerEncodeFunctionDataParameters & {
account: Address;
}
>;
Expand All @@ -47,18 +43,23 @@ type ArbOwnerClientPrepareFunctionDataResult = {
value: bigint;
};

type CreateArbOwnerClientParams = {
export type CreateArbOwnerClientParams = {
publicClient: PublicClient;
upgradeExecutor: Address | false; // this one is intentionally not optional, so you have to explicitly pass `upgradeExecutor: false` if you're not using one
};

export type ArbOwnerClient = ReturnType<typeof createArbOwnerClient>;

// arbOwnerSimulateContract
// arbOwnerPrepareTransactionRequest

export function createArbOwnerClient({
publicClient,
upgradeExecutor,
}: CreateArbOwnerClientParams): ArbOwnerClient {
}: CreateArbOwnerClientParams) {
return {
prepareFunctionData(
params: ArbOwnerFunctionDataParameters
params: ArbOwnerEncodeFunctionDataParameters
): ArbOwnerClientPrepareFunctionDataResult {
if (!upgradeExecutor) {
return {
Expand All @@ -82,7 +83,7 @@ export function createArbOwnerClient({
},

async prepareTransactionRequest(
params: ArbOwnerClientPrepareTransactionRequestParams
params: ArbOwnerPrepareTransactionRequestParameters
): Promise<PrepareTransactionRequestReturnType> {
const { to, data, value } = this.prepareFunctionData(params);

Expand All @@ -96,3 +97,65 @@ export function createArbOwnerClient({
},
};
}

function arbOwnerPrepareFunctionData(
params: ArbOwnerEncodeFunctionDataParameters
): ArbOwnerClientPrepareFunctionDataResult {
const upgradeExecutor = zeroAddress;

if (!upgradeExecutor) {
return {
to: arbOwner.address,
data: arbOwnerEncodeFunctionData(params),
value: BigInt(0),
};
}

return {
to: upgradeExecutor,
data: upgradeExecutorEncodeFunctionData({
functionName: 'executeCall',
args: [
arbOwner.address, // target
arbOwnerEncodeFunctionData(params), // targetCallData
],
}),
value: BigInt(0),
};
}

function applyDefaults<T>(obj: T,defaults: { abi: Abi }) {
return {
return {...obj, abi: defaults.abi}
};
}

function arbOwnerReadContract<TChain extends Chain | undefined>(
client: PublicClient<Transport, TChain>,
params: { functionName: string, args: any }
) {
return client.readContract({
address: arbOwner.address,
abi: arbOwner.abi,
functionName: params.functionName,
args: params.args
});
}

export async function arbOwnerPrepareTransactionRequest<
TChain extends Chain | undefined
>(
client: PublicClient<Transport, TChain>,
params: ArbOwnerPrepareTransactionRequestParameters
) {
const { to, data, value } = arbOwnerPrepareFunctionData(params);

// @ts-ignore
return client.prepareTransactionRequest({
chain: client.chain,
to,
data,
value,
account: params.account,
});
}
35 changes: 35 additions & 0 deletions src/decorators/arbOwnerPublicActions.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import {
Transport,
Chain,
Account,
Client,
PrepareTransactionRequestReturnType,
PublicClient,
} from 'viem';

import {
arbOwnerPrepareTransactionRequest,
ArbOwnerPrepareTransactionRequestParameters,
} from '../arbOwnerClient';

// arbOwnerReadContract
// arbOwnerSimulateContract
// arbOwnerPrepareTransactionRequest

type ArbOwnerPublicActions<
TChain extends Chain | undefined = Chain | undefined
> = {
arbOwnerPrepareTransactionRequest: (
args: ArbOwnerPrepareTransactionRequestParameters
) => Promise<PrepareTransactionRequestReturnType<TChain>>;
};

export function arbOwnerPublicActions<
TTransport extends Transport = Transport,
TChain extends Chain | undefined = Chain | undefined
>(client: PublicClient<TTransport, TChain>): ArbOwnerPublicActions<TChain> {
return {
arbOwnerPrepareTransactionRequest: (args) =>
arbOwnerPrepareTransactionRequest(client, args),
};
}
2 changes: 2 additions & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ import {
upgradeExecutorEncodeFunctionData,
UpgradeExecutorEncodeFunctionDataParameters,
} from './upgradeExecutor';
import { arbOwnerPublicActions } from './decorators/arbOwnerPublicActions';

import { ChainConfig, ChainConfigArbitrumParams } from './types/ChainConfig';
import { CoreContracts } from './types/CoreContracts';
Expand All @@ -45,6 +46,7 @@ import { prepareNodeConfig } from './prepareNodeConfig';
import * as utils from './utils';

export {
arbOwnerPublicActions,
createRollup,
createRollupPrepareTransactionRequest,
createRollupPrepareConfig,
Expand Down
14 changes: 14 additions & 0 deletions src/types/utils.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { Abi } from 'viem';
import { arbOwner } from '../contracts';

// https://twitter.com/mattpocockuk/status/1622730173446557697
export type Prettify<T> = {
Expand All @@ -9,3 +10,16 @@ export type GetFunctionName<TAbi extends Abi> = Extract<
TAbi[number],
{ type: 'function' }
>['name'];

export type ExtractReadFunctionsFromAbi<TAbi extends Abi> = Extract<
TAbi[number],
{ type: 'function'; stateMutability: 'view' | 'pure' }
>[];

export type ExtractWriteFunctionsFromAbi<TAbi extends Abi> = Extract<
TAbi[number],
{ type: 'function'; stateMutability: 'nonpayable' | 'payable' }
>[];

type X = GetFunctionName<ExtractReadFunctionsFromAbi<typeof arbOwner.abi>>;
type Y = GetFunctionName<ExtractWriteFunctionsFromAbi<typeof arbOwner.abi>>;

0 comments on commit 66b006e

Please sign in to comment.