diff --git a/src/lib/api.ts b/src/lib/api.ts index 35c19a9..38a29c4 100644 --- a/src/lib/api.ts +++ b/src/lib/api.ts @@ -60,6 +60,18 @@ class ApiClient { return response.json(); } + + async getDeployment(deploymentId: string) { + const response = await fetch(`/deploy?deploymentId=${deploymentId}`, { + method: "GET", + headers: { + "Content-Type": "application/json", + "Authorization": JSON.stringify(this.credentials) + }, + }); + + return response.json(); + } } export const API = new ApiClient(); diff --git a/src/lib/components/Depoy.svelte b/src/lib/components/Depoy.svelte index 9640874..8f3d502 100644 --- a/src/lib/components/Depoy.svelte +++ b/src/lib/components/Depoy.svelte @@ -1,5 +1,6 @@

- Contract deployment submitted to Defender!
+ {#if deploymentResult} + Contract deployed + {:else} + Contract deployment submitted to Defender! + {/if} +
{#if deploymentUrl} View Deployment diff --git a/src/lib/defender/index.ts b/src/lib/defender/index.ts index 2071f13..057bc64 100644 --- a/src/lib/defender/index.ts +++ b/src/lib/defender/index.ts @@ -68,4 +68,10 @@ export const updateDeployment = async (credentials: Credentials, updateReq: Upda address: updateReq.address, }); return response; -} \ No newline at end of file +} + +export const getDeployment = async (credentials: Credentials, deploymentId: string) => { + const client = getClient(credentials); + const response = await client.deploy.getDeployedContract(deploymentId); + return response; +} diff --git a/src/lib/ethereum/index.ts b/src/lib/ethereum/index.ts index 664a06f..ebc346b 100644 --- a/src/lib/ethereum/index.ts +++ b/src/lib/ethereum/index.ts @@ -1,6 +1,7 @@ import { type Eip1193Provider, BrowserProvider, ContractFactory } from 'ethers'; import { chainIds, type TenantNetworkResponse } from "$lib/models/network"; import type { DeployContractResult } from '$lib/models/ethereum'; +import { log } from '$lib/remix/logger'; function getEthereum(): Eip1193Provider { if (!window.ethereum) throw new Error('Injected provider not found'); @@ -22,6 +23,8 @@ export async function switchToNetwork(network: string | TenantNetworkResponse) { const current = await ethereum.request({ method: 'eth_chainId' }); if (parseInt(current, 16) === chainId) return; + log("[Defender Deploy] Switching network..."); + await ethereum.request({ method: 'wallet_switchEthereumChain', params: [{ chainId: `0x${chainId.toString(16)}` }], diff --git a/src/lib/models/approval-process.ts b/src/lib/models/approval-process.ts index c0b8f35..66f7f07 100644 --- a/src/lib/models/approval-process.ts +++ b/src/lib/models/approval-process.ts @@ -1,3 +1,5 @@ +import type { TenantNetworkResponse } from "./network"; + /** * Generic approval process model */ @@ -6,7 +8,7 @@ export type ApprovalProcess = { createdAt: string; name: string; component?: ComponentType; - network?: string; + network?: string | TenantNetworkResponse; via?: string; viaType?: 'EOA' | 'Contract' | 'Multisig' | 'Gnosis Safe' | 'Safe' | 'Gnosis Multisig' | 'Relayer' | 'Relayer Group' | 'Unknown' | 'Relayer Group' | 'Timelock Controller' | 'ERC20' | 'Governor' | 'Fireblocks'; multisigSender?: string; diff --git a/src/lib/models/ui.ts b/src/lib/models/ui.ts index 1658724..cfa0782 100644 --- a/src/lib/models/ui.ts +++ b/src/lib/models/ui.ts @@ -32,6 +32,7 @@ export type GlobalState = { viaType: 'EOA' | 'Safe' | 'Relayer'; via?: string; relayerId?: string; + network?: string; } approvalType?: 'existing' | 'new' | 'injected'; completed?: boolean; diff --git a/src/lib/state/state.svelte.ts b/src/lib/state/state.svelte.ts index 6db823a..6d4a1ae 100644 --- a/src/lib/state/state.svelte.ts +++ b/src/lib/state/state.svelte.ts @@ -78,4 +78,8 @@ export const setErrorBanner = (error?: string) => { export const addAPToDropdown = (approvalProcess: ApprovalProcess) => { globalState.approvalProcesses.push(approvalProcess); -}; +} + +export function setDeploymentCompleted(completed: boolean) { + globalState.form.completed = completed; +} diff --git a/src/lib/utils.ts b/src/lib/utils.ts index bdc2f09..f9786ed 100644 --- a/src/lib/utils.ts +++ b/src/lib/utils.ts @@ -10,6 +10,10 @@ * is the error from the catch statement. */ +import { getNetworkLiteral } from "./models/network"; +import type { ApprovalProcess } from "./models/approval-process"; +import type { TenantNetworkResponse } from "./models/network"; + type AttemptError = { msg: string; errorObject: any; @@ -47,4 +51,12 @@ export const abbreviateAddress = (address: string, size = 6) => { return `${address.slice(0, size)}...${address.slice(-size)}`; } -export const wait = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms)); \ No newline at end of file +export const wait = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms)); + +export const isSameNetwork = (a: string | TenantNetworkResponse, b: string | TenantNetworkResponse) => { + return getNetworkLiteral(a) === getNetworkLiteral(b); +} + +export const isDeploymentEnvironment = (approvalProcess: ApprovalProcess) => { + return approvalProcess.component?.includes('deploy'); +} diff --git a/src/routes/deploy/+server.ts b/src/routes/deploy/+server.ts index b347457..be1e50a 100644 --- a/src/routes/deploy/+server.ts +++ b/src/routes/deploy/+server.ts @@ -1,4 +1,4 @@ -import { deployContract, updateDeployment } from "$lib/defender"; +import { deployContract, getDeployment, updateDeployment } from "$lib/defender"; import type { Credentials } from "$lib/models/auth"; import type { DeployContractRequest, UpdateDeploymentRequest } from "$lib/models/deploy"; import { attempt } from "$lib/utils"; @@ -25,4 +25,29 @@ export async function PUT({ request }: { request: Request }) { } return json({ success: true, data: { result } }); -} \ No newline at end of file +} + +export async function GET({ request }: { request: Request }) { + const url = new URL(request.url); + const deploymentId = url.searchParams.get('deploymentId'); + const credentials = JSON.parse(request.headers.get('authorization') || '{}'); + + if (!deploymentId) { + return json({ success: false, error: "Missing deploymentId parameter" }); + } + + if (!credentials) { + return json({ success: false, error: "Missing Credentials" }); + } + + const [result, error] = await attempt(() => getDeployment(credentials, deploymentId)); + if (error) { + return json({ success: false, error: error.msg }); + } + + if (!result) { + return json({ success: false, error: "Deployment not found" }); + } + + return json({ success: true, data: { address: result.address, hash: result.txHash } }); +}