Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions modules/sdk-core/src/bitgo/safe/iSafes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
* @experimental The safe client surface is experimental and may change (including breaking
* changes) before the public release.
*/
import type { InitializeSafeResponse } from '@bitgo/public-types';
import { FinalizeSafeOptions, InitializeSafeOptions } from './iSafe';
import { Safe } from './safe';

Expand Down Expand Up @@ -62,10 +63,12 @@ export interface ISafes {
*/
generateSafe(params: CreateSafeOptions): Promise<Safe>;
/**
* Phase 1 — initialize a safe (metadata only, no key material).
* Phase 1 — initialize a safe (metadata only, no key material). The server response is just
* `{ id, status }` (no `label`/`enterpriseId`/`creator`/`users`/`createdAt` yet), so this
* returns that raw shape rather than a full `Safe`.
* @experimental
*/
initializeSafe(params: InitializeSafeOptions): Promise<Safe>;
initializeSafe(params: InitializeSafeOptions): Promise<InitializeSafeResponse>;
/**
* Phase 2 — run the 4 root key ceremonies tagged with `safeId`; returns the 12 minted key ids.
* @experimental
Expand Down
19 changes: 13 additions & 6 deletions modules/sdk-core/src/bitgo/safe/safes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,14 @@
* changes) before the public release.
*/
import * as t from 'io-ts';
import { FinalizeSafeBody, InitializeSafeBody, RootKeyTriplet, RootKeyType, SafeData } from '@bitgo/public-types';
import {
FinalizeSafeBody,
InitializeSafeBody,
InitializeSafeResponse,
RootKeyTriplet,
RootKeyType,
SafeData,
} from '@bitgo/public-types';
import { Environments } from '../../common';
import { IBaseCoin } from '../baseCoin';
import { BitGoBase } from '../bitgoBase';
Expand Down Expand Up @@ -87,19 +94,19 @@ export class Safes implements ISafes {
*/
async generateSafe(params: CreateSafeOptions): Promise<Safe> {
const safe = await this.initializeSafe({ label: params.label });
const rootKeys = await this.createSafeKeys({ ...params, safeId: safe.id() });
return await this.finalizeSafe(safe.id(), rootKeys);
const rootKeys = await this.createSafeKeys({ ...params, safeId: safe.id });
return await this.finalizeSafe(safe.id, rootKeys);
}

/**
* Phase 1 — initialize a safe (metadata only, no key material).
* POST /api/v2/enterprise/:eId/safes { label }
* Response is just `{ id, status }` — the safe has no label/roster/etc. yet.
* @experimental
*/
async initializeSafe(params: InitializeSafeOptions): Promise<Safe> {
async initializeSafe(params: InitializeSafeOptions): Promise<InitializeSafeResponse> {
const response = await postWithCodec(this.bitgo, this.url(), InitializeSafeBody, params).result();
const safeData = decodeWithCodec(SafeData, response, 'SafeData');
return new Safe(this.bitgo, safeData);
return decodeWithCodec(InitializeSafeResponse, response, 'InitializeSafeResponse');
}

/**
Expand Down
12 changes: 6 additions & 6 deletions modules/sdk-core/test/unit/bitgo/safe/safes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,15 +28,15 @@ describe('Safes', function () {
});

describe('initializeSafe', function () {
it('POSTs to the safes collection URL and returns a Safe', async function () {
const send = sinon.stub().returns({ result: sinon.stub().resolves(safeDataWire) });
it('POSTs to the safes collection URL and returns the initializing id/status', async function () {
const initializeResponseWire = { id: 'test-safe-id', status: 'initializing' };
const send = sinon.stub().returns({ result: sinon.stub().resolves(initializeResponseWire) });
mockBitGo.post.returns({ send });

const result = await safes.initializeSafe({ label: 'my safe' });

result.should.be.instanceof(Safe);
result.id().should.equal('test-safe-id');
result.enterpriseId().should.equal('test-enterprise-id');
result.id.should.equal('test-safe-id');
result.status.should.equal('initializing');
sinon.assert.calledWith(mockBitGo.post, '/enterprise/test-enterprise-id/safes');
sinon.assert.calledWith(send, { label: 'my safe' });
});
Expand Down Expand Up @@ -237,7 +237,7 @@ describe('Safes', function () {

describe('generateSafe', function () {
it('chains initialize → createSafeKeys → finalize, threading the safeId', async function () {
const initializing = new Safe(mockBitGo, { ...safeDataWire, status: 'initializing' } as any);
const initializing = { id: 'test-safe-id', status: 'initializing' as const };
const rootKeys = { rootKeys: { hot: {} } } as any;
const initStub = sinon.stub(safes, 'initializeSafe').resolves(initializing);
const keysStub = sinon.stub(safes, 'createSafeKeys').resolves(rootKeys);
Expand Down
Loading