|
4 | 4 | * @experimental The safe client surface is experimental and may change (including breaking |
5 | 5 | * changes) before the public release. |
6 | 6 | */ |
| 7 | +import * as t from 'io-ts'; |
7 | 8 | import { FinalizeSafeBody, InitializeSafeBody, RootKeyTriplet, RootKeyType, SafeData } from '@bitgo/public-types'; |
8 | 9 | import { Environments } from '../../common'; |
9 | 10 | import { IBaseCoin } from '../baseCoin'; |
@@ -40,6 +41,17 @@ const ROOT_COIN_BY_NETWORK: Record<'mainnet' | 'testnet', Record<RootKeyType, st |
40 | 41 | }, |
41 | 42 | }; |
42 | 43 |
|
| 44 | +/** |
| 45 | + * Wire shape of the paginated `GET /enterprise/:eId/safes` response. WP paginates with the v2 |
| 46 | + * `prevId`/`nextBatchPrevId` convention; the SDK re-exposes it as an opaque `cursor`/`nextCursor` |
| 47 | + * (see `list`). |
| 48 | + * @experimental |
| 49 | + */ |
| 50 | +const ListSafesResponse = t.intersection([ |
| 51 | + t.type({ safes: t.array(SafeData) }), |
| 52 | + t.partial({ nextBatchPrevId: t.string }), |
| 53 | +]); |
| 54 | + |
43 | 55 | /** |
44 | 56 | * Collection accessor for a single enterprise's safes, mirroring Wallets / Enterprises. |
45 | 57 | * Safe routes are enterprise-scoped (/api/v2/enterprise/:eId/safes), so the accessor is |
@@ -248,20 +260,38 @@ export class Safes implements ISafes { |
248 | 260 | } |
249 | 261 |
|
250 | 262 | /** |
251 | | - * List the enterprise's safes (cursor pagination). |
252 | | - * Implemented in WCN-1192 Phase 3 (blocked on WCN-1177). |
| 263 | + * List the enterprise's safes the caller is a member of (cursor pagination). |
| 264 | + * GET /api/v2/enterprise/:eId/safes?limit&prevId |
| 265 | + * |
| 266 | + * `cursor` is the opaque `nextCursor` returned by a previous call; page forward until |
| 267 | + * `nextCursor` is absent. |
253 | 268 | * @experimental |
254 | 269 | */ |
255 | 270 | async list(params: ListSafesOptions = {}): Promise<{ safes: Safe[]; nextCursor?: string }> { |
256 | | - throw new Error('Safes.list is not yet implemented (WCN-1192 Phase 3)'); |
| 271 | + // SDK exposes an opaque cursor; WP speaks prevId/nextBatchPrevId (v2 list convention). |
| 272 | + const query: { limit?: number; prevId?: string } = {}; |
| 273 | + if (params.limit !== undefined) { |
| 274 | + query.limit = params.limit; |
| 275 | + } |
| 276 | + if (params.cursor !== undefined) { |
| 277 | + query.prevId = params.cursor; |
| 278 | + } |
| 279 | + const response = await this.bitgo.get(this.url()).query(query).result(); |
| 280 | + const { safes, nextBatchPrevId } = decodeWithCodec(ListSafesResponse, response, 'ListSafesResponse'); |
| 281 | + return { |
| 282 | + safes: safes.map((safeData) => new Safe(this.bitgo, safeData)), |
| 283 | + nextCursor: nextBatchPrevId, |
| 284 | + }; |
257 | 285 | } |
258 | 286 |
|
259 | 287 | /** |
260 | | - * Fetch a single safe by id. |
261 | | - * Implemented in WCN-1192 Phase 3 (blocked on WCN-1177). |
| 288 | + * Fetch a single safe by id. Non-members get a 404 (existence is not leaked). |
| 289 | + * GET /api/v2/enterprise/:eId/safes/:safeId |
262 | 290 | * @experimental |
263 | 291 | */ |
264 | 292 | async get(params: GetSafeOptions): Promise<Safe> { |
265 | | - throw new Error('Safes.get is not yet implemented (WCN-1192 Phase 3)'); |
| 293 | + const response = await this.bitgo.get(this.url(`/${params.id}`)).result(); |
| 294 | + const safeData = decodeWithCodec(SafeData, response, 'SafeData'); |
| 295 | + return new Safe(this.bitgo, safeData); |
266 | 296 | } |
267 | 297 | } |
0 commit comments