signing.test.ts 1.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051
  1. import { beforeEach, describe, expect, it, vi } from 'vitest';
  2. import nacl from 'tweetnacl';
  3. import bs58 from 'bs58';
  4. import { signRequest } from '../packages/connectors/pacifica/src/signing';
  5. const seed = new Uint8Array(32).fill(7);
  6. const { secretKey, publicKey } = nacl.sign.keyPair.fromSeed(seed);
  7. const secretBase64 = Buffer.from(secretKey).toString('base64');
  8. describe('signRequest', () => {
  9. beforeEach(() => {
  10. vi.restoreAllMocks();
  11. });
  12. it('signs payloads according to Pacifica spec', () => {
  13. const body = { foo: 'bar', amount: 1 };
  14. vi.spyOn(Date, 'now').mockReturnValue(1_700_000_000_000);
  15. const apiKey = bs58.encode(publicKey);
  16. const { headers, body: serialized } = signRequest(
  17. {
  18. apiKey,
  19. secret: secretBase64
  20. },
  21. 'POST',
  22. '/orders',
  23. body
  24. );
  25. expect(headers['X-Pacific-Key']).toBe(apiKey);
  26. expect(headers['X-Pacific-Signature']).toBeTruthy();
  27. expect(headers['X-Pacific-Timestamp']).toBe('1700000000000');
  28. expect(serialized).toBe(JSON.stringify(body));
  29. const baseString = `${headers['X-Pacific-Timestamp']}:POST:/orders:${serialized}`;
  30. const signatureBytes = Buffer.from(headers['X-Pacific-Signature'], 'base64');
  31. const valid = nacl.sign.detached.verify(
  32. new TextEncoder().encode(baseString),
  33. signatureBytes,
  34. publicKey
  35. );
  36. expect(valid).toBe(true);
  37. });
  38. it('omits signature headers when api credentials are missing', () => {
  39. const { headers, body } = signRequest({}, 'GET', '/products/BTC', undefined);
  40. expect(headers).toEqual({});
  41. expect(body).toBe('');
  42. });
  43. });