Skip to content

Commit 72f5a20

Browse files
manumanu
authored andcommitted
Error in schema
1 parent cd11014 commit 72f5a20

File tree

14 files changed

+687
-2337
lines changed

14 files changed

+687
-2337
lines changed

nodes/webhooks/executions/Webhooks.ts

Lines changed: 26 additions & 531 deletions
Large diffs are not rendered by default.

nodes/webhooks/executions/Webhooks.ts.txt

Lines changed: 0 additions & 547 deletions
This file was deleted.
Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
import * as crypto from 'crypto';
2+
3+
interface CoinbaseCredentials {
4+
apiKey: string;
5+
privateKey: string;
6+
}
7+
8+
interface BuildCdpJwtParams {
9+
apiKeyId: string;
10+
apiKeySecret: string;
11+
method: string;
12+
host: string;
13+
path: string;
14+
}
15+
16+
function createCoinbaseJWT(credentials: CoinbaseCredentials, requestMethod: string, requestHost: string, requestPath: string): string {
17+
const { apiKey, privateKey } = credentials;
18+
19+
const pemKey = privateKey
20+
.replace(/\\n/g, '\n')
21+
.trim();
22+
23+
const keyName = apiKey;
24+
25+
const header = {
26+
alg: 'ES256',
27+
kid: keyName,
28+
typ: 'JWT',
29+
nonce: crypto.randomBytes(16).toString('hex')
30+
};
31+
32+
const now = Math.floor(Date.now() / 1000);
33+
const payload = {
34+
sub: keyName,
35+
iss: 'coinbase-cloud',
36+
nbf: now,
37+
exp: now + 120, // 2 minutes expiration
38+
aud: ['cdp_service'],
39+
uri: `${requestMethod} ${requestHost}${requestPath}`
40+
};
41+
42+
const base64UrlEncode = (obj: any): string => {
43+
return Buffer.from(JSON.stringify(obj))
44+
.toString('base64')
45+
.replace(/\+/g, '-')
46+
.replace(/\//g, '_')
47+
.replace(/=/g, '');
48+
};
49+
50+
const encodedHeader = base64UrlEncode(header);
51+
const encodedPayload = base64UrlEncode(payload);
52+
53+
const message = `${encodedHeader}.${encodedPayload}`;
54+
55+
const sign = crypto.createSign('SHA256');
56+
sign.update(message);
57+
sign.end();
58+
59+
const signature = sign.sign(pemKey);
60+
61+
const derSignature = signature;
62+
63+
let offset = 0;
64+
65+
if (derSignature[offset] === 0x30) {
66+
offset += 2;
67+
}
68+
69+
if (derSignature[offset] === 0x02) {
70+
offset += 1;
71+
const rLength = derSignature[offset];
72+
offset += 1;
73+
const r = derSignature.slice(offset, offset + rLength);
74+
offset += rLength;
75+
76+
if (derSignature[offset] === 0x02) {
77+
offset += 1;
78+
const sLength = derSignature[offset];
79+
offset += 1;
80+
const s = derSignature.slice(offset, offset + sLength);
81+
82+
const rPadded = r.length > 32 ? r.slice(r.length - 32) : Buffer.concat([Buffer.alloc(32 - r.length), r]);
83+
const sPadded = s.length > 32 ? s.slice(s.length - 32) : Buffer.concat([Buffer.alloc(32 - s.length), s]);
84+
85+
const rawSignature = Buffer.concat([rPadded, sPadded]);
86+
87+
const encodedSignature = rawSignature
88+
.toString('base64')
89+
.replace(/\+/g, '-')
90+
.replace(/\//g, '_')
91+
.replace(/=/g, '');
92+
93+
return `${encodedHeader}.${encodedPayload}.${encodedSignature}`;
94+
}
95+
}
96+
97+
throw new Error('Failed to parse signature');
98+
}
99+
100+
export async function buildCdpJwtAsync(params: BuildCdpJwtParams): Promise<string> {
101+
const { apiKeyId, apiKeySecret, method, host, path } = params;
102+
103+
return createCoinbaseJWT(
104+
{ apiKey: apiKeyId, privateKey: apiKeySecret },
105+
method,
106+
host,
107+
path
108+
);
109+
}

0 commit comments

Comments
 (0)