Skip to content

Commit

Permalink
Fix: Update not before (#30)
Browse files Browse the repository at this point in the history
* trigger staging deploy

* fix: long app id

* fix: verify staging endpoint (#18)

* Feat Siwe validation dev (#23)

* fix orb payload (#16)

fix orb payload

* update token type (#17)

Token type updated

* Transaction Id is Missing (#19)

Transaction ID is missing

* usdc (#21)

* Implement minikit walletauth command (#20)

* implement walletAuth on minikit side

* update demo to display wallet-auth

* remove http from validation

* refactor: wallet auth params validation

* adjust demo

* fixes

---------

Co-authored-by: Andy Wang <[email protected]>

* siwe-validation

Added logic for SIWE Validation and a valid working example. Note we rely mostly on nonce here and let the user do whatever they want to do. This is a pretty open implementation

---------

Co-authored-by: Igor Osipov <[email protected]>

* multiple-pay tokens

* fix token

* device and orb

* fix

* remove disabled

* update errors

Removed unused error codes

* reduce not before time

* verbose nonce

* update error

* saving nonce

* multiple addresses

* stringify-integer

* fix siwe

---------

Co-authored-by: Igor Osipov <[email protected]>
Co-authored-by: Igor Osipov <[email protected]>
  • Loading branch information
3 people authored May 22, 2024
1 parent 5d90fbd commit 0a5cbd3
Show file tree
Hide file tree
Showing 9 changed files with 103 additions and 39 deletions.
2 changes: 1 addition & 1 deletion cspell.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,5 @@
"yaml",
"json"
],
"words": ["idkit", "merkle", "OIDC", "SIWE"]
"words": ["idkit", "merkle", "OIDC", "SIWE", "USDCE"]
}
5 changes: 3 additions & 2 deletions demo/with-next/app/api/verify-siwe/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ const schema = yup.object({
signature: yup.string().required(),
address: yup.string().required(),
}),
nonce: yup.string().required(),
});

export const POST = async (req: NextRequest) => {
Expand All @@ -24,10 +25,10 @@ export const POST = async (req: NextRequest) => {
throw new Error("Invalid data");
}

const { siweResponsePayload } = validData;
const { siweResponsePayload, nonce } = validData;
const validMessage = await verifySiweMessage(
siweResponsePayload as MiniAppWalletAuthSuccessPayload,
"12345678"
nonce
);

return new Response(
Expand Down
79 changes: 60 additions & 19 deletions demo/with-next/components/ClientContent/Pay.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -81,22 +81,25 @@ export const Pay = () => {
};
}, []);

const onPayClick = useCallback(async (token: Tokens, amount: number) => {
const tokenAmount = tokenToDecimals(amount, token);

const payPayload: PayCommandInput = {
to: "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045",
token_amount: tokenAmount,
token: token,
description: "Test example payment for minikit",
reference: new Date().toISOString(),
};

const payload = MiniKit.commands.pay(payPayload);
setSentPayPayload({
payload,
});
}, []);
const onPayClick = useCallback(
async (token: Tokens, amount: number, address: string) => {
const tokenAmount = tokenToDecimals(amount, token);

const payPayload: PayCommandInput = {
to: address,
token_amount: tokenAmount.toString(),
token: token,
description: "Test example payment for minikit",
reference: new Date().toISOString(),
};

const payload = MiniKit.commands.pay(payPayload);
setSentPayPayload({
payload,
});
},
[]
);

return (
<div>
Expand All @@ -115,17 +118,55 @@ export const Pay = () => {
<div className="grid grid-cols-2 gap-x-4">
<button
className="bg-black text-white rounded-lg p-4 w-full"
onClick={() => onPayClick(Tokens.USDC, 0.1)}
onClick={() =>
onPayClick(
Tokens.USDCE,
0.1,
"0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045"
)
}
>
Send pay (USDC)
Send pay (USDCE)
</button>
<button
className="bg-black text-white rounded-lg p-4 w-full"
onClick={() => onPayClick(Tokens.WLD, 0.1)}
onClick={() =>
onPayClick(
Tokens.WLD,
0.1,
"0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045"
)
}
>
Send pay (WLD)
</button>
</div>
<div className="grid grid-cols-2 gap-x-4">
<button
className="bg-black text-white rounded-lg p-4 w-full"
onClick={() =>
onPayClick(
Tokens.USDCE,
0.1,
"0xc2eD884aEa29135AcaB517c0967225Bf15DeA6E9"
)
}
>
Send pay (USDCE) Addr 2
</button>
<button
className="bg-black text-white rounded-lg p-4 w-full"
onClick={() =>
onPayClick(
Tokens.WLD,
0.1,
"0xc2eD884aEa29135AcaB517c0967225Bf15DeA6E9"
)
}
>
Send pay (WLD) Addr 2
</button>
</div>
</div>

<hr />
Expand Down
13 changes: 8 additions & 5 deletions demo/with-next/components/ClientContent/WalletAuth.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ const walletAuthErrorPayloadSchema = yup.object({
export const WalletAuth = () => {
const [message, setMessage] = useState<string | null>(null);
const [generationError, setGenerationError] = useState<string | null>(null);
const [nonce, setNonce] = useState<string | null>(null);
const [receivedWalletAuthPayload, setReceivedWalletAuthPayload] =
useState<Record<string, any> | null>(null);

Expand Down Expand Up @@ -75,9 +76,10 @@ export const WalletAuth = () => {
},
body: JSON.stringify({
siweResponsePayload: payload,
nonce,
}),
});

const responseJson = await response.json();

setWalletAuthVerificationMessage(
Expand All @@ -93,18 +95,19 @@ export const WalletAuth = () => {
return () => {
MiniKit.unsubscribe(ResponseEvent.MiniAppWalletAuth);
};
}, []);
}, [nonce]);

const onGenerateMessageClick = useCallback(() => {
if (!MiniKit.isInstalled()) {
return;
}

const nonce = window.crypto.randomUUID();
setNonce(nonce);
const generateMessageResult = MiniKit.commands.walletAuth({
nonce: window.crypto.randomUUID(),
nonce: nonce,
requestId: "0",
expirationTime: new Date(new Date().getTime() + 7 * 24 * 60 * 60 * 1000),
notBefore: new Date(new Date().getTime() + 7 * 24 * 60 * 60 * 1000),
notBefore: new Date(new Date().getTime() - 24 * 60 * 60 * 1000),
});

if (!generateMessageResult) {
Expand Down
14 changes: 10 additions & 4 deletions src/helpers/siwe/siwe.ts
Original file line number Diff line number Diff line change
Expand Up @@ -164,15 +164,21 @@ export const verifySiweMessage = async (
}

if (nonce && siweMessageData.nonce !== nonce) {
throw new Error("Nonce mismatch");
throw new Error(
`Nonce mismatch. Got: ${siweMessageData.nonce}, Expected: ${nonce}`
);
}

if (statement && siweMessageData.statement !== statement) {
throw new Error("Statement mismatch");
throw new Error(
`Statement mismatch. Got: ${siweMessageData.statement}, Expected: ${statement}`
);
}

if (requestId && siweMessageData.request_id !== requestId) {
throw new Error("Request ID mismatch");
throw new Error(
`Request ID mismatch. Got: ${siweMessageData.request_id}, Expected: ${requestId}`
);
}

// Check ERC-191 Signature Matches
Expand All @@ -187,7 +193,7 @@ export const verifySiweMessage = async (
await contract.checkSignatures(
hashedMessage,
`0x${messageBytes}`,
signature
`0x${signature}`
);
} catch (error) {
throw new Error("Signature verification failed");
Expand Down
2 changes: 1 addition & 1 deletion src/types/commands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ export type VerifyCommandInput = {
export type PayCommandInput = {
reference: string;
to: string;
token_amount: number; // In Decimals
token_amount: string; // Stringified Decimals
token: Tokens;
network?: Network; // Optional
description: string;
Expand Down
5 changes: 1 addition & 4 deletions src/types/errors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,15 +28,12 @@ export const VerificationErrorMessage: Record<AppErrorCodes, string> = {
};

export enum PaymentErrorCodes {
MalformedRequest = "malformed_request",
InputError = "input_error",
PaymentRejected = "payment_rejected",
InvalidReceiver = "invalid_receiver",
InsufficientBalance = "insufficient_balance",
TransactionFailed = "transaction_failed",
InvalidTokenAddress = "invalid_token_address",
InvalidAppId = "invalid_app_id",
GenericError = "generic_error",
DuplicateReference = "duplicate_reference",
}

export enum PaymentErrorMessage {
Expand Down
4 changes: 2 additions & 2 deletions src/types/payment.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
export enum Tokens {
USDC = "USDC",
USDCE = "USDC.e",
WLD = "WLD",
}

export const TokenDecimals: { [key in Tokens]: number } = {
[Tokens.USDC]: 6,
[Tokens.USDCE]: 6,
[Tokens.WLD]: 18,
};

Expand Down
18 changes: 17 additions & 1 deletion tests/siwe.test.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { parseSiweMessage } from "@worldcoin/minikit-js";
import { parseSiweMessage, verifySiweMessage } from "@worldcoin/minikit-js";

const siweMessage = `https://test.com wants you to sign in with your Ethereum account:\n\
{{address}}\n\n\
Expand Down Expand Up @@ -31,6 +31,11 @@ Issued At: ${new Date().toISOString()}\n\
Expiration Time: 2024-05-03T00:00:00Z\n\
Request ID: 0`;

const signatureSiweMessage =
"http://localhost:3000 wants you to sign in with your Ethereum account:\n0xd809de3086ea4f53ed3979cead25e1ff72b564a3\n\n\nURI: http://localhost:3000/\nVersion: 1\nChain ID: 10\nNonce: 814434bd-ed2c-412e-aa2c-c4b266a42027\nIssued At: 2024-05-22T17:49:52.075Z\nExpiration Time: 2024-05-29T17:49:52.074Z\nNot Before: 2024-05-21T17:49:52.074Z\nRequest ID: 0\n";
const signature =
"f75530590312f5b36b6ef0003800003ba0af04640c72838580f76a3883d2365f397670d785475c39514629345cec307bcbe8c81fb85430da0dc3ef43c9a946d91b";

describe("Test SIWE Message Parsing", () => {
test("Correctly parses full SIWE message", () => {
parseSiweMessage(siweMessage);
Expand All @@ -46,4 +51,15 @@ describe("Test SIWE Message Parsing", () => {
"Missing 'Nonce: '"
);
});

test("Verify SIWE Message", () => {
const payload = {
status: "success",
message: signatureSiweMessage,
signature: signature,
address: "0xd809de3086ea4f53ed3979cead25e1ff72b564a3",
};

verifySiweMessage(payload, "814434bd-ed2c-412e-aa2c-c4b266a42027");
});
});

0 comments on commit 0a5cbd3

Please sign in to comment.