Skip to content

Commit

Permalink
Merge pull request #131 from OpenZeppelin/plat-1927-platform-sdk-acti…
Browse files Browse the repository at this point in the history
…ons-missing-function-typo

Added missing actions utilities
  • Loading branch information
MCarlomagno authored Oct 19, 2023
2 parents 01cfc88 + 16fe827 commit 837bf9c
Show file tree
Hide file tree
Showing 14 changed files with 202 additions and 182 deletions.
5 changes: 4 additions & 1 deletion examples/create-action/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,12 @@ async function main() {
const creds = { apiKey: process.env.API_KEY, apiSecret: process.env.API_SECRET };
const client = new Defender(creds);

client.action.validatePath('./code');
const encodedZippedCode = await client.action.getEncodedZippedCodeFromFolder('./code');

const myAction = {
name: 'my-action',
encodedZippedCode: await client.action.getEncodedZippedCodeFromFolder('./code'),
encodedZippedCode,
trigger: {
type: 'schedule',
frequencyMinutes: 1500,
Expand Down
6 changes: 4 additions & 2 deletions examples/create-batch-proposal/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,15 @@ const contracts = [
address: ERC20Token,
name: 'ERC20 Token',
network: 'goerli',
abi: '[{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"mint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"}]',
abi:
'[{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"mint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"}]',
},
{
address: RolesContract,
network: 'goerli',
name: 'Roles Contract',
abi: '[{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"grantRole","outputs":[],"stateMutability":"nonpayable","type":"function"}]',
abi:
'[{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"grantRole","outputs":[],"stateMutability":"nonpayable","type":"function"}]',
},
];

Expand Down
13 changes: 13 additions & 0 deletions packages/action/src/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {
} from './models/action-run.res';
import { ActionDeleteResponse, ActionListResponse, ActionResponse } from './models/response';
import { zipFolder, zipSources } from './zip';
import { tailLogsFor, validateId, validatePath } from './utils';

type SourceFiles = {
'index.js': string;
Expand Down Expand Up @@ -136,4 +137,16 @@ export class ActionClient extends BaseApiClient {
return await api.get(`/secrets`);
});
}

public tailLogsFor(actionId: string): Promise<void> {
return tailLogsFor(this, actionId);
}

public validateId(id: string): void {
validateId(id);
}

public validatePath(path: string): void {
validatePath(path);
}
}
68 changes: 68 additions & 0 deletions packages/action/src/utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import { existsSync } from 'fs';
import { ActionClient } from './api';
import {
ActionRunErrorData,
ActionRunListItemResponse,
ActionRunStatus,
ActionRunSuccessData,
} from './models/action-run.res';

/**
* Regex Validator for Action and Action run IDs.
*/
export function validateId(id: string): void {
const regex = /^[0-9a-z]{8}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{12}$/i;
if (regex.test(id)) {
return;
} else {
throw new Error(`invalid id '${id}'`);
}
}

/**
* Checks if path exists, otherwise throws an error.
*/
export function validatePath(path: string): void {
if (existsSync(path)) {
return;
} else {
throw new Error(`path ${path} does not exist`);
}
}

export async function tailLogsFor(client: ActionClient, actionId: string) {
try {
validateId(actionId);
console.warn(`\nPolling latest runs of action '${actionId}'...\n`);
// Poll action runs every 2 seconds and if there are new runs, get run details and print them out.
let lastRun: ActionRunListItemResponse | undefined;
while (true) {
const newRuns = await client.listActionRuns(actionId, {});
// If cached last run id has changed
if (newRuns.items[0]?.actionRunId !== lastRun?.actionRunId) {
lastRun = newRuns.items[0]; // cache new last run to avoid duplicates.
if (!lastRun) throw new Error('last run not found');

const status = lastRun.status as ActionRunStatus;
if (status === 'pending') {
lastRun = undefined; // clean up so we can check it again on the next poll.
} else if (status === 'error') {
const runDetails = (await client.getActionRun(lastRun.actionRunId)) as ActionRunErrorData;
console.log(`\nError: ${runDetails.message}`);
runDetails.decodedLogs ? console.log(`\n${runDetails.decodedLogs}`) : console.log(`No logs available.`);
} else if (status === 'success') {
const runDetails = (await client.getActionRun(lastRun.actionRunId)) as ActionRunSuccessData;
console.log(`\n${runDetails.decodedLogs}`);
} else if (status === 'throttled') {
console.warn(
`\nThis autotask run was canceled since the hourly run capacity for your account has been exceeded. Contact us at defender-support@openzeppelin.com for additional capacity.`,
);
}
}

await new Promise((resolve) => setTimeout(resolve, 2000));
}
} catch (e) {
throw e;
}
}
8 changes: 4 additions & 4 deletions packages/base/src/api/__mocks__/axios-error.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,13 @@ export const mockAxiosError: AxiosError = {
config: {
url: '/relayer',
method: 'get',
headers: {
headers: ({
'Accept': 'application/json, text/plain, */*',
'X-Api-Key': '4Rfp2GEHDjgesA6MdseUM1n8B8kT9hgs',
'Authorization': 'Bearer WRONG',
'Content-Type': 'application/json',
'User-Agent': 'axios/0.21.4',
} as unknown as AxiosRequestHeaders,
} as unknown) as AxiosRequestHeaders,
baseURL: 'https://defender-api.openzeppelin.com/',
timeout: 0,
xsrfCookieName: 'XSRF-TOKEN',
Expand Down Expand Up @@ -142,13 +142,13 @@ export const mockAxiosError: AxiosError = {
maxContentLength: -1,
maxBodyLength: -1,
data: undefined,
headers: {
headers: ({
'Accept': 'application/json, text/plain, */*',
'X-Api-Key': '4Rfp2GEHDjgesA6MdseUM1n8B8kT9hgs',
'Authorization': 'Bearer WRONG',
'Content-Type': 'application/json',
'User-Agent': 'axios/0.21.4',
} as unknown as AxiosRequestHeaders,
} as unknown) as AxiosRequestHeaders,
},
request: {
_eventsCount: 7,
Expand Down
4 changes: 2 additions & 2 deletions packages/deploy/src/api/block-explorer-api-key.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,10 @@ describe('Block Explorer Api Key Client', () => {
key: 'random-key',
};
beforeEach(() => {
client = new DeployClient({
client = (new DeployClient({
apiKey: 'key',
apiSecret: 'secret',
}) as unknown as TestClient<DeployClient>;
}) as unknown) as TestClient<DeployClient>;
createAuthenticatedApi.mockClear();
});
describe('constructor', () => {
Expand Down
4 changes: 2 additions & 2 deletions packages/deploy/src/api/deployment.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,10 @@ describe('Deploy Client', () => {
verifySourceCode: true,
};
beforeEach(() => {
deployClient = new DeployClient({
deployClient = (new DeployClient({
apiKey: 'key',
apiSecret: 'secret',
}) as unknown as TestClient<DeployClient>;
}) as unknown) as TestClient<DeployClient>;
createAuthenticatedApi.mockClear();
});
describe('constructor', () => {
Expand Down
28 changes: 23 additions & 5 deletions packages/monitor/src/api/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ describe('MonitorClient', () => {
};

beforeEach(() => {
monitor = new MonitorClient({ apiKey: 'key', apiSecret: 'secret' }) as unknown as TestMonitorClient;
monitor = (new MonitorClient({ apiKey: 'key', apiSecret: 'secret' }) as unknown) as TestMonitorClient;
createAuthenticatedApi.mockClear();
listBlockwatchersSpy = jest.spyOn(monitor, 'listBlockwatchers').mockImplementation(async () => [
{
Expand Down Expand Up @@ -184,8 +184,17 @@ describe('MonitorClient', () => {

describe('create', () => {
it('passes correct BLOCK type arguments to the API', async () => {
const { name, network, paused, type, addresses, abi, txCondition, eventConditions, functionConditions } =
createBlockPayload;
const {
name,
network,
paused,
type,
addresses,
abi,
txCondition,
eventConditions,
functionConditions,
} = createBlockPayload;

const expectedApiRequest = {
paused,
Expand Down Expand Up @@ -292,8 +301,17 @@ describe('MonitorClient', () => {
it('passes correct BLOCK type arguments to the API', async () => {
jest.spyOn(monitor, 'get').mockImplementation(async () => oldBlockMonitor);

const { name, network, paused, type, addresses, abi, txCondition, eventConditions, functionConditions } =
createBlockPayload;
const {
name,
network,
paused,
type,
addresses,
abi,
txCondition,
eventConditions,
functionConditions,
} = createBlockPayload;

const expectedApiRequest = {
paused,
Expand Down
2 changes: 1 addition & 1 deletion packages/network/src/api/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ describe('NetworkClient', () => {
let networkClient: TestNetworkClient;

beforeEach(() => {
networkClient = new NetworkClient({ apiKey: 'key', apiSecret: 'secret' }) as unknown as TestNetworkClient;
networkClient = (new NetworkClient({ apiKey: 'key', apiSecret: 'secret' }) as unknown) as TestNetworkClient;
createAuthenticatedApi.mockClear();
});

Expand Down
2 changes: 1 addition & 1 deletion packages/proposal/src/models/simulation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ export type Log = [
Address | string[] | string,
Address | string[] | string,
Address | string[] | string,
...(Address | string[] | string)[],
...(Address | string[] | string)[]
];
export type BigUInt = string | string | number;

Expand Down
4 changes: 2 additions & 2 deletions packages/relay-signer/src/action/index-rate.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,10 @@ describe('ActionRelayer', () => {
let relayer: TestActionRelayer;

beforeEach(async function () {
relayer = new ActionRelayer({
relayer = (new ActionRelayer({
credentials: JSON.stringify(credentials),
relayerARN: 'arn',
}) as unknown as TestActionRelayer;
}) as unknown) as TestActionRelayer;
});

describe('get rate limited', () => {
Expand Down
4 changes: 2 additions & 2 deletions packages/relay-signer/src/action/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,10 @@ describe('ActionRelayer', () => {
let relayer: TestActionRelayer;

beforeEach(async function () {
relayer = new ActionRelayer({
relayer = (new ActionRelayer({
credentials: JSON.stringify(credentials),
relayerARN: 'arn',
}) as unknown as TestActionRelayer;
}) as unknown) as TestActionRelayer;
});

describe('constructor', () => {
Expand Down
2 changes: 1 addition & 1 deletion packages/relay-signer/src/ethers/provider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,6 @@ export class DefenderRelayProvider extends StaticJsonRpcProvider {
}

getSigner(): JsonRpcSigner {
return new DefenderRelaySigner(this.relayer, this, {}) as any as JsonRpcSigner;
return (new DefenderRelaySigner(this.relayer, this, {}) as any) as JsonRpcSigner;
}
}
Loading

0 comments on commit 837bf9c

Please sign in to comment.