@farcaster/frame-node 0.0.18 → 0.0.21
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +10 -12
- package/dist/farcaster.js +35 -2
- package/esm/farcaster.d.ts +19 -29
- package/esm/farcaster.js +49 -57
- package/esm/index.d.ts +7 -7
- package/esm/index.js +7 -7
- package/esm/jfs.d.ts +16 -33
- package/esm/jfs.js +74 -93
- package/esm/neynar.d.ts +2 -2
- package/esm/neynar.js +12 -14
- package/esm/tsconfig.tsbuildinfo +1 -1
- package/esm/types.d.ts +20 -27
- package/esm/types.js +6 -6
- package/esm/util.d.ts +2 -2
- package/esm/util.js +2 -4
- package/esm/webhook.d.ts +6 -17
- package/esm/webhook.js +18 -23
- package/package.json +2 -2
- package/src/farcaster.ts +1 -1
package/README.md
CHANGED
|
@@ -1,19 +1,17 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @farcaster/frame-node
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Utility methods for Mini App backends
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
pnpm add @farcaster/frame-node
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Documentation
|
|
4
12
|
|
|
5
13
|
- `parseWebhookEvent`: parses and verifies webhook events, using a `VerifyAppKey` method
|
|
6
14
|
- `verifyJsonFarcasterSignature`: verifies a [JSON Farcaster Signature](https://github.com/farcasterxyz/protocol/discussions/208) payload, using a `VerifyAppKey` method
|
|
7
15
|
- `createJsonFarcasterSignature`: creates a [JSON Farcaster Signature](https://github.com/farcasterxyz/protocol/discussions/208) payload
|
|
8
16
|
|
|
9
17
|
For signature verification, you need to pass in a `VerifyAppKey` method that verifies that an app key is valid for an FID. You can use the included `verifyAppKeyWithNeynar` which uses [Neynar](https://neynar.com) and requires the `NEYNAR_API_KEY` environment variable to be defined.
|
|
10
|
-
|
|
11
|
-
Not yet stable. [Learn more](https://github.com/farcasterxyz/frames/wiki/frames-v2-developer-playground-preview).
|
|
12
|
-
|
|
13
|
-
## Install
|
|
14
|
-
|
|
15
|
-
Install using your favorite manager:
|
|
16
|
-
|
|
17
|
-
```
|
|
18
|
-
npm install @farcaster/frame-node
|
|
19
|
-
```
|
package/dist/farcaster.js
CHANGED
|
@@ -1,7 +1,40 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
2
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
36
|
exports.createVerifyAppKeyWithHub = exports.signedKeyRequestAbi = void 0;
|
|
4
|
-
const
|
|
37
|
+
const AbiParameters = __importStar(require("ox/AbiParameters"));
|
|
5
38
|
const zod_1 = require("zod");
|
|
6
39
|
const types_1 = require("./types");
|
|
7
40
|
exports.signedKeyRequestAbi = [
|
|
@@ -53,7 +86,7 @@ const createVerifyAppKeyWithHub = (hubUrl, requestOptions) => async (fid, appKey
|
|
|
53
86
|
if (!signerEvent) {
|
|
54
87
|
return { valid: false };
|
|
55
88
|
}
|
|
56
|
-
const decoded =
|
|
89
|
+
const decoded = AbiParameters.decode(exports.signedKeyRequestAbi, Buffer.from(signerEvent.signerEventBody.metadata, 'base64'));
|
|
57
90
|
if (decoded.length !== 1) {
|
|
58
91
|
throw new types_1.BaseError('Error decoding metadata');
|
|
59
92
|
}
|
package/esm/farcaster.d.ts
CHANGED
|
@@ -1,29 +1,19 @@
|
|
|
1
|
-
import type
|
|
2
|
-
export declare const signedKeyRequestAbi: readonly [
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
readonly
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
readonly name:
|
|
11
|
-
readonly type:
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
readonly
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
},
|
|
21
|
-
]
|
|
22
|
-
readonly name: 'SignedKeyRequest'
|
|
23
|
-
readonly type: 'tuple'
|
|
24
|
-
},
|
|
25
|
-
]
|
|
26
|
-
export declare const createVerifyAppKeyWithHub: (
|
|
27
|
-
hubUrl: string,
|
|
28
|
-
requestOptions?: RequestInit,
|
|
29
|
-
) => VerifyAppKey
|
|
1
|
+
import { type VerifyAppKey } from './types';
|
|
2
|
+
export declare const signedKeyRequestAbi: readonly [{
|
|
3
|
+
readonly components: readonly [{
|
|
4
|
+
readonly name: "requestFid";
|
|
5
|
+
readonly type: "uint256";
|
|
6
|
+
}, {
|
|
7
|
+
readonly name: "requestSigner";
|
|
8
|
+
readonly type: "address";
|
|
9
|
+
}, {
|
|
10
|
+
readonly name: "signature";
|
|
11
|
+
readonly type: "bytes";
|
|
12
|
+
}, {
|
|
13
|
+
readonly name: "deadline";
|
|
14
|
+
readonly type: "uint256";
|
|
15
|
+
}];
|
|
16
|
+
readonly name: "SignedKeyRequest";
|
|
17
|
+
readonly type: "tuple";
|
|
18
|
+
}];
|
|
19
|
+
export declare const createVerifyAppKeyWithHub: (hubUrl: string, requestOptions?: RequestInit) => VerifyAppKey;
|
package/esm/farcaster.js
CHANGED
|
@@ -1,67 +1,59 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { z } from 'zod'
|
|
3
|
-
import { BaseError } from './types'
|
|
1
|
+
import * as AbiParameters from 'ox/AbiParameters';
|
|
2
|
+
import { z } from 'zod';
|
|
3
|
+
import { BaseError } from './types';
|
|
4
4
|
export const signedKeyRequestAbi = [
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
]
|
|
5
|
+
{
|
|
6
|
+
components: [
|
|
7
|
+
{
|
|
8
|
+
name: 'requestFid',
|
|
9
|
+
type: 'uint256',
|
|
10
|
+
},
|
|
11
|
+
{
|
|
12
|
+
name: 'requestSigner',
|
|
13
|
+
type: 'address',
|
|
14
|
+
},
|
|
15
|
+
{
|
|
16
|
+
name: 'signature',
|
|
17
|
+
type: 'bytes',
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
name: 'deadline',
|
|
21
|
+
type: 'uint256',
|
|
22
|
+
},
|
|
23
|
+
],
|
|
24
|
+
name: 'SignedKeyRequest',
|
|
25
|
+
type: 'tuple',
|
|
26
|
+
},
|
|
27
|
+
];
|
|
28
28
|
const hubResponseSchema = z.object({
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
const url = new URL('/v1/onChainSignersByFid', hubUrl)
|
|
41
|
-
url.searchParams.append('fid', fid.toString())
|
|
42
|
-
const response = await fetch(url, requestOptions)
|
|
29
|
+
events: z.array(z.object({
|
|
30
|
+
signerEventBody: z.object({
|
|
31
|
+
key: z.string(),
|
|
32
|
+
metadata: z.string(),
|
|
33
|
+
}),
|
|
34
|
+
})),
|
|
35
|
+
});
|
|
36
|
+
export const createVerifyAppKeyWithHub = (hubUrl, requestOptions) => async (fid, appKey) => {
|
|
37
|
+
const url = new URL('/v1/onChainSignersByFid', hubUrl);
|
|
38
|
+
url.searchParams.append('fid', fid.toString());
|
|
39
|
+
const response = await fetch(url, requestOptions);
|
|
43
40
|
if (response.status !== 200) {
|
|
44
|
-
|
|
41
|
+
throw new BaseError(`Non-200 response received: ${await response.text()}`);
|
|
45
42
|
}
|
|
46
|
-
const responseJson = await response.json()
|
|
47
|
-
const parsedResponse = hubResponseSchema.safeParse(responseJson)
|
|
43
|
+
const responseJson = await response.json();
|
|
44
|
+
const parsedResponse = hubResponseSchema.safeParse(responseJson);
|
|
48
45
|
if (parsedResponse.error) {
|
|
49
|
-
|
|
46
|
+
throw new BaseError('Error parsing Hub response', parsedResponse.error);
|
|
50
47
|
}
|
|
51
|
-
const appKeyLower = appKey.toLowerCase()
|
|
52
|
-
const signerEvent = parsedResponse.data.events.find(
|
|
53
|
-
(event) => event.signerEventBody.key.toLowerCase() === appKeyLower,
|
|
54
|
-
)
|
|
48
|
+
const appKeyLower = appKey.toLowerCase();
|
|
49
|
+
const signerEvent = parsedResponse.data.events.find((event) => event.signerEventBody.key.toLowerCase() === appKeyLower);
|
|
55
50
|
if (!signerEvent) {
|
|
56
|
-
|
|
51
|
+
return { valid: false };
|
|
57
52
|
}
|
|
58
|
-
const decoded = AbiParameters.decode(
|
|
59
|
-
signedKeyRequestAbi,
|
|
60
|
-
Buffer.from(signerEvent.signerEventBody.metadata, 'base64'),
|
|
61
|
-
)
|
|
53
|
+
const decoded = AbiParameters.decode(signedKeyRequestAbi, Buffer.from(signerEvent.signerEventBody.metadata, 'base64'));
|
|
62
54
|
if (decoded.length !== 1) {
|
|
63
|
-
|
|
55
|
+
throw new BaseError('Error decoding metadata');
|
|
64
56
|
}
|
|
65
|
-
const appFid = Number(decoded[0].requestFid)
|
|
66
|
-
return { valid: true, appFid }
|
|
67
|
-
|
|
57
|
+
const appFid = Number(decoded[0].requestFid);
|
|
58
|
+
return { valid: true, appFid };
|
|
59
|
+
};
|
package/esm/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
export * from '@farcaster/frame-core'
|
|
2
|
-
export * from './jfs'
|
|
3
|
-
export * from './neynar'
|
|
4
|
-
export * from './farcaster'
|
|
5
|
-
export * from './types'
|
|
6
|
-
export * from './webhook'
|
|
7
|
-
export * from './util'
|
|
1
|
+
export * from '@farcaster/frame-core';
|
|
2
|
+
export * from './jfs';
|
|
3
|
+
export * from './neynar';
|
|
4
|
+
export * from './farcaster';
|
|
5
|
+
export * from './types';
|
|
6
|
+
export * from './webhook';
|
|
7
|
+
export * from './util';
|
package/esm/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
export * from '@farcaster/frame-core'
|
|
2
|
-
export * from './jfs'
|
|
3
|
-
export * from './neynar'
|
|
4
|
-
export * from './farcaster'
|
|
5
|
-
export * from './types'
|
|
6
|
-
export * from './webhook'
|
|
7
|
-
export * from './util'
|
|
1
|
+
export * from '@farcaster/frame-core';
|
|
2
|
+
export * from './jfs';
|
|
3
|
+
export * from './neynar';
|
|
4
|
+
export * from './farcaster';
|
|
5
|
+
export * from './types';
|
|
6
|
+
export * from './webhook';
|
|
7
|
+
export * from './util';
|
package/esm/jfs.d.ts
CHANGED
|
@@ -1,38 +1,21 @@
|
|
|
1
|
-
import type
|
|
2
|
-
import { BaseError, type VerifyAppKey, type VerifyJfsResult } from './types'
|
|
1
|
+
import { type EncodedJsonFarcasterSignatureSchema } from '@farcaster/frame-core';
|
|
2
|
+
import { BaseError, type VerifyAppKey, type VerifyJfsResult } from './types';
|
|
3
3
|
export declare namespace VerifyJsonFarcasterSignature {
|
|
4
|
-
|
|
5
|
-
| InvalidJfsDataError
|
|
6
|
-
| InvalidJfsAppKeyError
|
|
7
|
-
| VerifyAppKeyError
|
|
4
|
+
type ErrorType = InvalidJfsDataError | InvalidJfsAppKeyError | VerifyAppKeyError;
|
|
8
5
|
}
|
|
9
|
-
export declare class InvalidJfsDataError<
|
|
10
|
-
|
|
11
|
-
> extends BaseError<C> {
|
|
12
|
-
readonly name = 'VerifyJsonFarcasterSignature.InvalidDataError'
|
|
6
|
+
export declare class InvalidJfsDataError<C extends Error | undefined = undefined> extends BaseError<C> {
|
|
7
|
+
readonly name = "VerifyJsonFarcasterSignature.InvalidDataError";
|
|
13
8
|
}
|
|
14
|
-
export declare class InvalidJfsAppKeyError<
|
|
15
|
-
|
|
16
|
-
> extends BaseError<C> {
|
|
17
|
-
readonly name = 'VerifyJsonFarcasterSignature.InvalidAppKeyError'
|
|
9
|
+
export declare class InvalidJfsAppKeyError<C extends Error | undefined = undefined> extends BaseError<C> {
|
|
10
|
+
readonly name = "VerifyJsonFarcasterSignature.InvalidAppKeyError";
|
|
18
11
|
}
|
|
19
|
-
export declare class VerifyAppKeyError<
|
|
20
|
-
|
|
21
|
-
> extends BaseError<C> {
|
|
22
|
-
readonly name = 'VerifyJsonFarcasterSignature.VerifyAppKeyError'
|
|
12
|
+
export declare class VerifyAppKeyError<C extends Error | undefined = undefined> extends BaseError<C> {
|
|
13
|
+
readonly name = "VerifyJsonFarcasterSignature.VerifyAppKeyError";
|
|
23
14
|
}
|
|
24
|
-
export declare function verifyJsonFarcasterSignature(
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
privateKey,
|
|
32
|
-
payload,
|
|
33
|
-
}: {
|
|
34
|
-
fid: number
|
|
35
|
-
type: 'app_key'
|
|
36
|
-
privateKey: Uint8Array
|
|
37
|
-
payload: Uint8Array
|
|
38
|
-
}): EncodedJsonFarcasterSignatureSchema
|
|
15
|
+
export declare function verifyJsonFarcasterSignature(data: unknown, verifyAppKey: VerifyAppKey): Promise<VerifyJfsResult>;
|
|
16
|
+
export declare function createJsonFarcasterSignature({ fid, type, privateKey, payload, }: {
|
|
17
|
+
fid: number;
|
|
18
|
+
type: 'app_key';
|
|
19
|
+
privateKey: Uint8Array;
|
|
20
|
+
payload: Uint8Array;
|
|
21
|
+
}): EncodedJsonFarcasterSignatureSchema;
|
package/esm/jfs.js
CHANGED
|
@@ -1,102 +1,83 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
} from '
|
|
5
|
-
import { ed25519 } from '@noble/curves/ed25519'
|
|
6
|
-
import { BaseError } from './types'
|
|
7
|
-
import { bytesToHex, hexToBytes } from './util'
|
|
1
|
+
import { encodedJsonFarcasterSignatureSchema, jsonFarcasterSignatureHeaderSchema, } from '@farcaster/frame-core';
|
|
2
|
+
import { ed25519 } from '@noble/curves/ed25519';
|
|
3
|
+
import { BaseError, } from './types';
|
|
4
|
+
import { bytesToHex, hexToBytes } from './util';
|
|
8
5
|
export class InvalidJfsDataError extends BaseError {
|
|
9
|
-
|
|
6
|
+
name = 'VerifyJsonFarcasterSignature.InvalidDataError';
|
|
10
7
|
}
|
|
11
8
|
export class InvalidJfsAppKeyError extends BaseError {
|
|
12
|
-
|
|
9
|
+
name = 'VerifyJsonFarcasterSignature.InvalidAppKeyError';
|
|
13
10
|
}
|
|
14
11
|
export class VerifyAppKeyError extends BaseError {
|
|
15
|
-
|
|
12
|
+
name = 'VerifyJsonFarcasterSignature.VerifyAppKeyError';
|
|
16
13
|
}
|
|
17
14
|
export async function verifyJsonFarcasterSignature(data, verifyAppKey) {
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
)
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
error instanceof Error ? error : undefined,
|
|
73
|
-
)
|
|
74
|
-
}
|
|
75
|
-
if (!appKeyResult.valid) {
|
|
76
|
-
throw new InvalidJfsAppKeyError('App key not valid for FID')
|
|
77
|
-
}
|
|
78
|
-
return { fid, appFid: appKeyResult.appFid, payload }
|
|
15
|
+
//
|
|
16
|
+
// Parse, decode and validate data
|
|
17
|
+
//
|
|
18
|
+
const body = encodedJsonFarcasterSignatureSchema.safeParse(data);
|
|
19
|
+
if (body.success === false) {
|
|
20
|
+
throw new InvalidJfsDataError('Error parsing data', body.error);
|
|
21
|
+
}
|
|
22
|
+
let headerData;
|
|
23
|
+
try {
|
|
24
|
+
headerData = JSON.parse(Buffer.from(body.data.header, 'base64url').toString('utf-8'));
|
|
25
|
+
}
|
|
26
|
+
catch (error) {
|
|
27
|
+
throw new InvalidJfsDataError('Error decoding and parsing header');
|
|
28
|
+
}
|
|
29
|
+
const header = jsonFarcasterSignatureHeaderSchema.safeParse(headerData);
|
|
30
|
+
if (header.success === false) {
|
|
31
|
+
throw new InvalidJfsDataError('Error parsing header', header.error);
|
|
32
|
+
}
|
|
33
|
+
const payload = Buffer.from(body.data.payload, 'base64url');
|
|
34
|
+
const signature = Buffer.from(body.data.signature, 'base64url');
|
|
35
|
+
if (signature.byteLength !== 64) {
|
|
36
|
+
throw new InvalidJfsDataError('Invalid signature length');
|
|
37
|
+
}
|
|
38
|
+
//
|
|
39
|
+
// Verify the signature
|
|
40
|
+
//
|
|
41
|
+
const fid = header.data.fid;
|
|
42
|
+
const appKey = header.data.key;
|
|
43
|
+
const appKeyBytes = hexToBytes(appKey);
|
|
44
|
+
const signedInput = new Uint8Array(Buffer.from(body.data.header + '.' + body.data.payload));
|
|
45
|
+
let verifyResult;
|
|
46
|
+
try {
|
|
47
|
+
verifyResult = ed25519.verify(signature, signedInput, appKeyBytes);
|
|
48
|
+
}
|
|
49
|
+
catch (e) {
|
|
50
|
+
throw new InvalidJfsDataError('Error checking signature', e instanceof Error ? e : undefined);
|
|
51
|
+
}
|
|
52
|
+
if (!verifyResult) {
|
|
53
|
+
throw new InvalidJfsDataError('Invalid signature');
|
|
54
|
+
}
|
|
55
|
+
//
|
|
56
|
+
// Verify that the app key belongs to the FID
|
|
57
|
+
//
|
|
58
|
+
let appKeyResult;
|
|
59
|
+
try {
|
|
60
|
+
appKeyResult = await verifyAppKey(fid, appKey);
|
|
61
|
+
}
|
|
62
|
+
catch (error) {
|
|
63
|
+
throw new VerifyAppKeyError('Error verifying app key', error instanceof Error ? error : undefined);
|
|
64
|
+
}
|
|
65
|
+
if (!appKeyResult.valid) {
|
|
66
|
+
throw new InvalidJfsAppKeyError('App key not valid for FID');
|
|
67
|
+
}
|
|
68
|
+
return { fid, appFid: appKeyResult.appFid, payload };
|
|
79
69
|
}
|
|
80
|
-
export function createJsonFarcasterSignature({
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
Buffer.from(encodedHeader + '.' + encodedPayload, 'utf-8'),
|
|
94
|
-
)
|
|
95
|
-
const signature = ed25519.sign(signatureInput, privateKey)
|
|
96
|
-
const encodedSignature = Buffer.from(signature).toString('base64url')
|
|
97
|
-
return {
|
|
98
|
-
header: encodedHeader,
|
|
99
|
-
payload: encodedPayload,
|
|
100
|
-
signature: encodedSignature,
|
|
101
|
-
}
|
|
70
|
+
export function createJsonFarcasterSignature({ fid, type, privateKey, payload, }) {
|
|
71
|
+
const publicKey = ed25519.getPublicKey(privateKey);
|
|
72
|
+
const header = { fid, type, key: bytesToHex(publicKey) };
|
|
73
|
+
const encodedHeader = Buffer.from(JSON.stringify(header)).toString('base64url');
|
|
74
|
+
const encodedPayload = Buffer.from(payload).toString('base64url');
|
|
75
|
+
const signatureInput = new Uint8Array(Buffer.from(encodedHeader + '.' + encodedPayload, 'utf-8'));
|
|
76
|
+
const signature = ed25519.sign(signatureInput, privateKey);
|
|
77
|
+
const encodedSignature = Buffer.from(signature).toString('base64url');
|
|
78
|
+
return {
|
|
79
|
+
header: encodedHeader,
|
|
80
|
+
payload: encodedPayload,
|
|
81
|
+
signature: encodedSignature,
|
|
82
|
+
};
|
|
102
83
|
}
|
package/esm/neynar.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import type { VerifyAppKey } from './types'
|
|
2
|
-
export declare const verifyAppKeyWithNeynar: VerifyAppKey
|
|
1
|
+
import type { VerifyAppKey } from './types';
|
|
2
|
+
export declare const verifyAppKeyWithNeynar: VerifyAppKey;
|
package/esm/neynar.js
CHANGED
|
@@ -1,15 +1,13 @@
|
|
|
1
|
-
import { createVerifyAppKeyWithHub } from './farcaster'
|
|
2
|
-
const apiKey = process.env.NEYNAR_API_KEY || ''
|
|
1
|
+
import { createVerifyAppKeyWithHub } from './farcaster';
|
|
2
|
+
const apiKey = process.env.NEYNAR_API_KEY || '';
|
|
3
3
|
export const verifyAppKeyWithNeynar = async (fid, appKey) => {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
return verifier(fid, appKey)
|
|
15
|
-
}
|
|
4
|
+
if (!apiKey) {
|
|
5
|
+
throw new Error('Environment variable NEYNAR_API_KEY needs to be set to use Neynar for app key verification');
|
|
6
|
+
}
|
|
7
|
+
const verifier = createVerifyAppKeyWithHub('https://hub-api.neynar.com', {
|
|
8
|
+
headers: {
|
|
9
|
+
'x-api-key': apiKey,
|
|
10
|
+
},
|
|
11
|
+
});
|
|
12
|
+
return verifier(fid, appKey);
|
|
13
|
+
};
|