@farcaster/frame-node 0.0.9 → 0.0.11
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/dist/farcaster.d.ts +1 -1
- package/dist/farcaster.js +17 -17
- package/dist/index.d.ts +7 -7
- package/dist/jfs.d.ts +3 -3
- package/dist/jfs.js +19 -19
- package/dist/neynar.d.ts +1 -1
- package/dist/neynar.js +4 -4
- package/dist/types.d.ts +1 -1
- package/dist/types.js +1 -1
- package/dist/util.js +2 -2
- package/dist/webhook.d.ts +2 -2
- package/dist/webhook.js +4 -4
- package/esm/farcaster.d.ts +29 -19
- package/esm/farcaster.js +57 -49
- package/esm/index.d.ts +7 -7
- package/esm/index.js +7 -7
- package/esm/jfs.d.ts +33 -16
- package/esm/jfs.js +93 -74
- package/esm/neynar.d.ts +2 -2
- package/esm/neynar.js +14 -12
- package/esm/tsconfig.tsbuildinfo +1 -1
- package/esm/types.d.ts +27 -20
- package/esm/types.js +6 -6
- package/esm/util.d.ts +2 -2
- package/esm/util.js +4 -2
- package/esm/webhook.d.ts +17 -6
- package/esm/webhook.js +23 -18
- package/package.json +7 -5
- package/src/farcaster.ts +34 -36
- package/src/index.ts +7 -7
- package/src/jfs.ts +55 -50
- package/src/neynar.ts +11 -11
- package/src/types.ts +15 -15
- package/src/util.ts +3 -3
- package/src/webhook.ts +18 -14
package/esm/jfs.js
CHANGED
|
@@ -1,83 +1,102 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
import {
|
|
2
|
+
encodedJsonFarcasterSignatureSchema,
|
|
3
|
+
jsonFarcasterSignatureHeaderSchema,
|
|
4
|
+
} from '@farcaster/frame-core'
|
|
5
|
+
import { ed25519 } from '@noble/curves/ed25519'
|
|
6
|
+
import { BaseError } from './types'
|
|
7
|
+
import { bytesToHex, hexToBytes } from './util'
|
|
5
8
|
export class InvalidJfsDataError extends BaseError {
|
|
6
|
-
|
|
9
|
+
name = 'VerifyJsonFarcasterSignature.InvalidDataError'
|
|
7
10
|
}
|
|
8
11
|
export class InvalidJfsAppKeyError extends BaseError {
|
|
9
|
-
|
|
12
|
+
name = 'VerifyJsonFarcasterSignature.InvalidAppKeyError'
|
|
10
13
|
}
|
|
11
14
|
export class VerifyAppKeyError extends BaseError {
|
|
12
|
-
|
|
15
|
+
name = 'VerifyJsonFarcasterSignature.VerifyAppKeyError'
|
|
13
16
|
}
|
|
14
17
|
export async function verifyJsonFarcasterSignature(data, verifyAppKey) {
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
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
|
-
|
|
18
|
+
//
|
|
19
|
+
// Parse, decode and validate data
|
|
20
|
+
//
|
|
21
|
+
const body = encodedJsonFarcasterSignatureSchema.safeParse(data)
|
|
22
|
+
if (body.success === false) {
|
|
23
|
+
throw new InvalidJfsDataError('Error parsing data', body.error)
|
|
24
|
+
}
|
|
25
|
+
let headerData
|
|
26
|
+
try {
|
|
27
|
+
headerData = JSON.parse(
|
|
28
|
+
Buffer.from(body.data.header, 'base64url').toString('utf-8'),
|
|
29
|
+
)
|
|
30
|
+
} catch (error) {
|
|
31
|
+
throw new InvalidJfsDataError('Error decoding and parsing header')
|
|
32
|
+
}
|
|
33
|
+
const header = jsonFarcasterSignatureHeaderSchema.safeParse(headerData)
|
|
34
|
+
if (header.success === false) {
|
|
35
|
+
throw new InvalidJfsDataError('Error parsing header', header.error)
|
|
36
|
+
}
|
|
37
|
+
const payload = Buffer.from(body.data.payload, 'base64url')
|
|
38
|
+
const signature = Buffer.from(body.data.signature, 'base64url')
|
|
39
|
+
if (signature.byteLength !== 64) {
|
|
40
|
+
throw new InvalidJfsDataError('Invalid signature length')
|
|
41
|
+
}
|
|
42
|
+
//
|
|
43
|
+
// Verify the signature
|
|
44
|
+
//
|
|
45
|
+
const fid = header.data.fid
|
|
46
|
+
const appKey = header.data.key
|
|
47
|
+
const appKeyBytes = hexToBytes(appKey)
|
|
48
|
+
const signedInput = new Uint8Array(
|
|
49
|
+
Buffer.from(body.data.header + '.' + body.data.payload),
|
|
50
|
+
)
|
|
51
|
+
let verifyResult
|
|
52
|
+
try {
|
|
53
|
+
verifyResult = ed25519.verify(signature, signedInput, appKeyBytes)
|
|
54
|
+
} catch (e) {
|
|
55
|
+
throw new InvalidJfsDataError(
|
|
56
|
+
'Error checking signature',
|
|
57
|
+
e instanceof Error ? e : undefined,
|
|
58
|
+
)
|
|
59
|
+
}
|
|
60
|
+
if (!verifyResult) {
|
|
61
|
+
throw new InvalidJfsDataError('Invalid signature')
|
|
62
|
+
}
|
|
63
|
+
//
|
|
64
|
+
// Verify that the app key belongs to the FID
|
|
65
|
+
//
|
|
66
|
+
let appKeyResult
|
|
67
|
+
try {
|
|
68
|
+
appKeyResult = await verifyAppKey(fid, appKey)
|
|
69
|
+
} catch (error) {
|
|
70
|
+
throw new VerifyAppKeyError(
|
|
71
|
+
'Error verifying app key',
|
|
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 }
|
|
69
79
|
}
|
|
70
|
-
export function createJsonFarcasterSignature({
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
80
|
+
export function createJsonFarcasterSignature({
|
|
81
|
+
fid,
|
|
82
|
+
type,
|
|
83
|
+
privateKey,
|
|
84
|
+
payload,
|
|
85
|
+
}) {
|
|
86
|
+
const publicKey = ed25519.getPublicKey(privateKey)
|
|
87
|
+
const header = { fid, type, key: bytesToHex(publicKey) }
|
|
88
|
+
const encodedHeader = Buffer.from(JSON.stringify(header)).toString(
|
|
89
|
+
'base64url',
|
|
90
|
+
)
|
|
91
|
+
const encodedPayload = Buffer.from(payload).toString('base64url')
|
|
92
|
+
const signatureInput = new Uint8Array(
|
|
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
|
+
}
|
|
83
102
|
}
|
package/esm/neynar.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { VerifyAppKey } from
|
|
2
|
-
export declare const verifyAppKeyWithNeynar: VerifyAppKey
|
|
1
|
+
import type { VerifyAppKey } from './types'
|
|
2
|
+
export declare const verifyAppKeyWithNeynar: VerifyAppKey
|
package/esm/neynar.js
CHANGED
|
@@ -1,13 +1,15 @@
|
|
|
1
|
-
import { createVerifyAppKeyWithHub } from
|
|
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
|
-
}
|
|
4
|
+
if (!apiKey) {
|
|
5
|
+
throw new Error(
|
|
6
|
+
'Environment variable NEYNAR_API_KEY needs to be set to use Neynar for app key verification',
|
|
7
|
+
)
|
|
8
|
+
}
|
|
9
|
+
const verifier = createVerifyAppKeyWithHub('https://hub-api.neynar.com', {
|
|
10
|
+
headers: {
|
|
11
|
+
'x-api-key': apiKey,
|
|
12
|
+
},
|
|
13
|
+
})
|
|
14
|
+
return verifier(fid, appKey)
|
|
15
|
+
}
|