Skip to content

Commit

Permalink
feat: added missing address and transaction field for FrameValidation…
Browse files Browse the repository at this point in the history
…Data type (#287)
  • Loading branch information
Zizzamia authored Apr 16, 2024
1 parent f08e4c2 commit d61861f
Show file tree
Hide file tree
Showing 9 changed files with 73 additions and 10 deletions.
5 changes: 5 additions & 0 deletions .changeset/tame-mayflies-itch.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@coinbase/onchainkit': patch
---

- **feat**: added missing `address` and `transaction` field for `FrameValidationData` type. By @zizzamia & @SamuelLHuber #287
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

### Minor Changes

- b8aa317: - **feat**: init Open Frame spec support. By @zizzamia @daria-github @neekolas #285
- **feat**: init Open Frame spec support. By @zizzamia @daria-github @neekolas #285 b8aa317

## 0.11.3

Expand Down
4 changes: 4 additions & 0 deletions site/docs/pages/frame/types.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ interface FrameRequest {

```ts
interface FrameValidationData {
address: string | null; // The connected wallet address of the interacting user.
button: number; // Number of the button clicked
following: boolean; // Indicates if the viewer clicking the frame follows the cast author
input: string; // Text input from the viewer typing in the frame
Expand All @@ -130,6 +131,9 @@ interface FrameValidationData {
state: {
serialized: string; // Serialized state (e.g. JSON) passed to the frame server
};
transaction: {
hash: string;
} | null;
valid: boolean; // Indicates if the frame is valid
}
```
Expand Down
57 changes: 49 additions & 8 deletions src/frame/getFrameMessage.test.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { Address } from 'viem';
import { getFrameMessage } from './getFrameMessage';
import { getMockFrameRequest } from './getMockFrameRequest';
import { neynarBulkUserLookup } from '../utils/neynar/user/neynarBulkUserLookup';
Expand All @@ -17,26 +18,36 @@ jest.mock('../utils/neynar/frame/neynarFrameValidation', () => {
});

function mockNeynarResponse(
fid: number,
addresses: string[] | undefined,
action: {
address?: Address;
transaction?: {
hash: string;
};
},
interactor: {
fid: number;
verifications?: string[] | undefined;
},
lookupMock: jest.Mock,
frameValidationMock: jest.Mock = jest.fn(),
) {
const neynarResponse = {
users: [
{
verifications: addresses,
verifications: interactor?.verifications,
},
],
};
lookupMock.mockResolvedValue(neynarResponse);

frameValidationMock.mockResolvedValue({
valid: true,
address: action?.address || null,
interactor: {
fid,
verified_accounts: addresses,
fid: interactor.fid,
verified_accounts: interactor?.verifications,
},
transaction: action?.transaction || null,
valid: true,
});
}

Expand Down Expand Up @@ -117,8 +128,11 @@ describe('getFrameValidatedMessage', () => {
const fid = 1234;
const addresses = ['0xaddr1'];
mockNeynarResponse(
fid,
addresses,
{},
{
fid,
verifications: addresses,
},
neynarBulkUserLookup as jest.Mock,
neynarFrameValidation as jest.Mock,
);
Expand All @@ -128,4 +142,31 @@ describe('getFrameValidatedMessage', () => {
const result = await getFrameMessage(fakeFrameData as FrameRequest);
expect(result?.message?.interactor.fid).toEqual(fid);
});

it('should return the address and transaction if they exist', async () => {
const fid = 1234;
const addresses = ['0xaddr1'];
mockNeynarResponse(
{
address: 'address' as Address,
transaction: {
hash: 'transaction',
},
},
{
fid,
verifications: addresses,
},
neynarBulkUserLookup as jest.Mock,
neynarFrameValidation as jest.Mock,
);
const fakeFrameData = {
trustedData: {},
};
const result = await getFrameMessage(fakeFrameData as FrameRequest);
expect(result?.message?.address).toEqual('address');
expect(result?.message?.transaction).toEqual({
hash: 'transaction',
});
});
});
3 changes: 3 additions & 0 deletions src/frame/getMockFrameRequest.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { Address } from 'viem';
import { FrameRequest, MockFrameRequest, MockFrameRequestOptions } from './types';

/**
Expand All @@ -14,6 +15,7 @@ function getMockFrameRequest(
return {
...request,
mockFrameData: {
address: null,
button: request.untrustedData.buttonIndex,
following: !!options?.following,
input: request.untrustedData.inputText,
Expand All @@ -31,6 +33,7 @@ function getMockFrameRequest(
state: {
serialized: request.untrustedData.state || '',
},
transaction: null,
valid: true,
raw: {
valid: true,
Expand Down
4 changes: 4 additions & 0 deletions src/frame/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ export interface FrameRequest {
* Simplified Object model with the raw Neynar data if-needed.
*/
export interface FrameValidationData {
address: string | null; // The connected wallet address of the interacting user.
button: number; // Number of the button clicked
following: boolean; // Indicates if the viewer clicking the frame follows the cast author
input: string; // Text input from the viewer typing in the frame
Expand All @@ -56,6 +57,9 @@ export interface FrameValidationData {
state: {
serialized: string; // Serialized state (e.g. JSON) passed to the frame server
};
transaction: {
hash: string;
} | null;
valid: boolean; // Indicates if the frame is valid
}

Expand Down
2 changes: 2 additions & 0 deletions src/utils/neynar/frame/convertToNeynarResponseModel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ export function convertToNeynarResponseModel(data: any): FrameValidationData | u
const interactor = action?.interactor;

return {
address: action?.address || null,
button: action?.tapped_button?.index,
following: action?.interactor?.viewer_context?.following,
input: action?.input?.text,
Expand All @@ -37,6 +38,7 @@ export function convertToNeynarResponseModel(data: any): FrameValidationData | u
state: {
serialized: action?.state?.serialized || '',
},
transaction: action?.transaction || null,
valid: neynarResponse.valid,
};
}
4 changes: 4 additions & 0 deletions src/utils/neynar/frame/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
export interface NeynarFrameValidationInternalModel {
valid: boolean;
action: {
address?: string;
object: string;
interactor: {
object: string;
Expand Down Expand Up @@ -134,5 +135,8 @@ export interface NeynarFrameValidationInternalModel {
};
};
timestamp: string;
transaction?: {
hash: string;
};
};
}
2 changes: 1 addition & 1 deletion src/version.ts
Original file line number Diff line number Diff line change
@@ -1 +1 @@
export const version = '0.12.0';
export const version = '0.12.1';

0 comments on commit d61861f

Please sign in to comment.