Skip to content

Commit

Permalink
Delegate execute call from Profile to Keychain
Browse files Browse the repository at this point in the history
  • Loading branch information
JunichiSugiura committed Nov 15, 2024
1 parent e3c5898 commit 58a3759
Show file tree
Hide file tree
Showing 6 changed files with 126 additions and 26 deletions.
73 changes: 73 additions & 0 deletions packages/controller/src/controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ export default class ControllerProvider extends BaseProvider {
},
methods: {
openPurchaseCredits: this.openPurchaseCredits.bind(this),
openExecute: normalize(() => this.openExecute.bind(this)),
},
rpcUrl: this.rpc.toString(),
username,
Expand Down Expand Up @@ -221,6 +222,20 @@ export default class ControllerProvider extends BaseProvider {
this.keychain.openPurchaseCredits();
}

private openExecute(calls: any) {
if (!this.keychain || !this.iframes.keychain) {
console.error(new NotReadyToConnect().message);
return;
}
if (!this.iframes.profile) {
console.error("Profile is not ready");
return;
}
this.iframes.profile.close();
this.iframes.keychain.open();
this.keychain.execute(calls);
}

async delegateAccount() {
if (!this.keychain) {
console.error(new NotReadyToConnect().message);
Expand Down Expand Up @@ -255,3 +270,61 @@ export default class ControllerProvider extends BaseProvider {
});
}
}

export function normalize<Promise>(
fn: (origin: string) => Promise,
): (origin: string) => Promise {
return (origin: string) => fn(normalizeOrigin(origin));
}

const DEFAULT_PORT_BY_PROTOCOL: { [index: string]: string } = {
"http:": "80",
"https:": "443",
};

const URL_REGEX = /^(https?:)?\/\/([^/:]+)?(:(\d+))?/;

const opaqueOriginSchemes = ["file:", "data:"];

/**
* Converts a src value into an origin.
*/
export function normalizeOrigin(src: string): string {
if (src && opaqueOriginSchemes.find((scheme) => src.startsWith(scheme))) {
// The origin of the child document is an opaque origin and its
// serialization is "null"
// https://html.spec.whatwg.org/multipage/origin.html#origin
return "null";
}

// Note that if src is undefined, then srcdoc is being used instead of src
// and we can follow this same logic below to get the origin of the parent,
// which is the origin that we will need to use.

const location = document.location;

const regexResult = URL_REGEX.exec(src);
let protocol: string;
let hostname: string;
let port: string;

if (regexResult) {
// It's an absolute URL. Use the parsed info.
// regexResult[1] will be undefined if the URL starts with //
protocol = regexResult[1] ? regexResult[1] : location.protocol;
hostname = regexResult[2];
port = regexResult[4];
} else {
// It's a relative path. Use the current location's info.
protocol = location.protocol;
hostname = location.hostname;
port = location.port;
}

// If the port is the default for the protocol, we don't want to add it to the origin string
// or it won't match the message's event.origin.

const portSuffix =
port && port !== DEFAULT_PORT_BY_PROTOCOL[protocol] ? `:${port}` : "";
return `${protocol}//${hostname}${portSuffix}`;
}
1 change: 1 addition & 0 deletions packages/controller/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@ export interface Keychain {
username(): string;
fetchControllers(contractAddresses: string[]): Promise<ControllerAccounts>;
openPurchaseCredits(): void;
openExecute(): void;
}
export interface Profile {
navigate(path: string): void;
Expand Down
13 changes: 9 additions & 4 deletions packages/profile/src/components/context/connection.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import {
normalize,
STRK_CONTRACT_ADDRESS,
} from "@cartridge/utils";
import { constants, getChecksumAddress, RpcProvider } from "starknet";
import { Call, constants, getChecksumAddress, RpcProvider } from "starknet";
import { useNavigate, useSearchParams } from "react-router-dom";

type ConnectionContextType = {
Expand All @@ -26,12 +26,17 @@ type ConnectionContextType = {
};

type ParentMethods = {
close: () => Promise<void>;
openPurchaseCredits: () => Promise<void>;
close: () => void;
openPurchaseCredits: () => void;
openExecute: (calls: Call[]) => void;
};

const initialState: ConnectionContextType = {
parent: { close: async () => {}, openPurchaseCredits: async () => {} },
parent: {
close: () => {},
openPurchaseCredits: () => {},
openExecute: () => {},
},
provider: new RpcProvider({ nodeUrl: import.meta.env.VITE_RPC_SEPOLIA }),
chainId: "",
erc20: [],
Expand Down
57 changes: 41 additions & 16 deletions packages/profile/src/components/inventory/token/send.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {
LayoutHeader,
} from "@/components/layout";
import { useAccount } from "@/hooks/account";
import { useConnection } from "@/hooks/context";
import { useToken } from "@/hooks/token";
import {
ArrowIcon,
Expand All @@ -25,31 +26,38 @@ import { useCallback, useMemo } from "react";
import { useForm } from "react-hook-form";
import { Link, useParams } from "react-router-dom";
import { constants } from "starknet";
import { parseEther } from "viem";
import { z } from "zod";

export function SendToken() {
const { address: tokenAddress } = useParams<{ address: string }>();
const { address } = useAccount();
const { parent } = useConnection();
const t = useToken({ tokenAddress: tokenAddress! });

const formSchema = useMemo(
() =>
z.object({
to: z
.string()
.startsWith("0x", { message: 'Starknet address must start with "0x"' })
.startsWith("0x", {
message: 'Starknet address must start with "0x"',
})
.min(62, {
message: "Starknet address must be at least 61 characters long",
})
.refine((addr) => {
try {
return BigInt(addr) < constants.PRIME
} catch {
return false
}
}, {
message: "Please input a valid Starknet address",
}),
.refine(
(addr) => {
try {
return BigInt(addr) < constants.PRIME;
} catch {
return false;
}
},
{
message: "Please input a valid Starknet address",
},
),
amount: z.coerce.number({ message: "Amount is required" }).positive(),
}),
[],
Expand All @@ -62,9 +70,27 @@ export function SendToken() {
},
});

const onSubmit = useCallback((values: z.infer<typeof formSchema>) => {
console.log(values);
}, []);
const onSubmit = useCallback(
(values: z.infer<typeof formSchema>) => {
if (!t) return;

const amount = parseEther(values.amount.toString());

parent.openExecute([
{
contractAddress: t?.meta.address,
entrypoint: "increaseAllowance",
calldata: [values.to, amount, "0x0"],
},
{
contractAddress: t?.meta.address,
entrypoint: "transfer",
calldata: [values.to, amount, "0x0"],
},
]);
},
[t, parent],
);

const amount = form.watch("amount");

Expand Down Expand Up @@ -126,9 +152,7 @@ export function SendToken() {
<div className="flex items-center justify-between">
<FormLabel>Amount</FormLabel>
<div className="flex items-center gap-2">
<FormLabel>
Balance:
</FormLabel>
<FormLabel>Balance:</FormLabel>
<div className="text-xs">
{t.balance.formatted} {t.meta.symbol}
</div>
Expand All @@ -140,6 +164,7 @@ export function SendToken() {
type="number"
placeholder="0.01"
{...field}
value={field.value ?? ""}
className="[&::-webkit-inner-spin-button]:appearance-none"
/>
{countervalue && (
Expand Down
4 changes: 1 addition & 3 deletions packages/profile/src/components/inventory/token/token.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -82,9 +82,7 @@ function Credits() {
</LayoutContent>

<LayoutFooter>
<Button onClick={() => parent.openPurchaseCredits().catch(() => {})}>
Purchase
</Button>
<Button onClick={() => parent.openPurchaseCredits()}>Purchase</Button>
</LayoutFooter>
</LayoutContainer>
);
Expand Down
4 changes: 1 addition & 3 deletions packages/profile/src/components/layout/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,7 @@ export function LayoutContainer({
const { parent, chainId, setIsVisible } = useConnection();
const onClose = useCallback(() => {
setIsVisible(false);
parent.close().catch(() => {
/* Always fails for some reason */
});
parent.close();
}, [parent, setIsVisible]);

return (
Expand Down

0 comments on commit 58a3759

Please sign in to comment.