@solana/rpc-subscriptions
Version:
A library for subscribing to Solana RPC notifications
1 lines • 37.3 kB
Source Map (JSON)
{"version":3,"sources":["../src/rpc-integer-overflow-error.ts","../src/rpc-default-config.ts","../../event-target-impl/src/index.browser.ts","../src/rpc-subscriptions-autopinger.ts","../src/rpc-subscriptions-channel-pool-internal.ts","../src/rpc-subscriptions-channel-pool.ts","../src/rpc-subscriptions-json.ts","../src/rpc-subscriptions-json-bigint.ts","../src/rpc-subscriptions-channel.ts","../src/rpc-subscriptions-coalescer.ts","../src/rpc-subscriptions-transport.ts","../src/rpc-subscriptions.ts"],"names":["AbortController","pipe","transformChannelInboundMessages","transformChannelOutboundMessages"],"mappings":";;;;;;;;;;;AAGO,SAAS,uCAAA,CACZ,UACA,EAAA,OAAA,EACA,KACuD,EAAA;AACvD,EAAA,IAAI,aAAgB,GAAA,EAAA;AACpB,EAAA,IAAI,OAAO,OAAA,CAAQ,CAAC,CAAA,KAAM,QAAU,EAAA;AAChC,IAAM,MAAA,WAAA,GAAc,OAAQ,CAAA,CAAC,CAAI,GAAA,CAAA;AACjC,IAAA,MAAM,YAAY,WAAc,GAAA,EAAA;AAChC,IAAA,MAAM,gBAAgB,WAAc,GAAA,GAAA;AACpC,IAAI,IAAA,SAAA,IAAa,CAAK,IAAA,aAAA,IAAiB,EAAI,EAAA;AACvC,MAAA,aAAA,GAAgB,WAAc,GAAA,IAAA;AAAA,KACvB,MAAA,IAAA,SAAA,IAAa,CAAK,IAAA,aAAA,IAAiB,EAAI,EAAA;AAC9C,MAAA,aAAA,GAAgB,WAAc,GAAA,IAAA;AAAA,KACvB,MAAA,IAAA,SAAA,IAAa,CAAK,IAAA,aAAA,IAAiB,EAAI,EAAA;AAC9C,MAAA,aAAA,GAAgB,WAAc,GAAA,IAAA;AAAA,KAC3B,MAAA;AACH,MAAA,aAAA,GAAgB,WAAc,GAAA,IAAA;AAAA;AAClC,GACG,MAAA;AACH,IAAA,aAAA,GAAgB,CAAK,EAAA,EAAA,OAAA,CAAQ,CAAC,CAAA,CAAE,UAAU,CAAA,EAAA,CAAA;AAAA;AAE9C,EAAM,MAAA,IAAA,GACF,QAAQ,MAAS,GAAA,CAAA,GACX,QACK,KAAM,CAAA,CAAC,EACP,GAAI,CAAA,CAAA,QAAA,KAAa,OAAO,QAAa,KAAA,QAAA,GAAW,IAAI,QAAQ,CAAA,CAAA,CAAA,GAAM,QAAS,CAC3E,CAAA,IAAA,CAAK,GAAG,CACb,GAAA,MAAA;AACV,EAAM,MAAA,KAAA,GAAQ,IAAI,WAAA,CAAY,mCAAqC,EAAA;AAAA,IAC/D,aAAA;AAAA,IACA,OAAA;AAAA,IACA,UAAA;AAAA,IACA,iBAAmB,EAAA,IAAA,GAAO,CAAc,WAAA,EAAA,IAAI,CAAO,EAAA,CAAA,GAAA,EAAA;AAAA,IACnD,KAAA;AAAA,IACA,GAAI,IAAA,KAAS,MAAY,GAAA,EAAE,MAAS,GAAA;AAAA,GACvC,CAAA;AACD,EAAA,qBAAA,CAAsB,OAAO,uCAAuC,CAAA;AACpE,EAAO,OAAA,KAAA;AACX;;;ACtCO,IAAM,gCAET,GAAA;AAAA,EACA,iBAAmB,EAAA,WAAA;AAAA,EACnB,iBAAA,CAAkB,OAAS,EAAA,OAAA,EAAS,KAAO,EAAA;AACvC,IAAA,MAAM,uCAAwC,CAAA,OAAA,CAAQ,UAAY,EAAA,OAAA,EAAS,KAAK,CAAA;AAAA;AAExF;;;ACXO,IAAMA,IAAkB,UAAW,CAAA,eAAA;;;ACU1C,IAAM,YAAe,GAAA;AAAA,EACjB,OAAS,EAAA,KAAA;AAAA,EACT,MAAQ,EAAA;AACZ,CAAA;AAQO,SAAS,sCAAkG,CAAA;AAAA,EAC9G,WAAa,EAAA,iBAAA;AAAA,EACb,OAAA;AAAA,EACA;AACJ,CAA+B,EAAA;AAC3B,EAAI,IAAA,UAAA;AACJ,EAAA,SAAS,QAAW,GAAA;AAChB,IAAA,OAAA,CAAQ,IAAK,CAAA,YAAY,CAAE,CAAA,KAAA,CAAM,CAAC,CAAe,KAAA;AAC7C,MAAI,IAAA,aAAA,CAAc,CAAG,EAAA,0DAA0D,CAAG,EAAA;AAC9E,QAAA,qBAAA,CAAsB,KAAM,EAAA;AAAA;AAChC,KACH,CAAA;AAAA;AAEL,EAAA,SAAS,gBAAmB,GAAA;AACxB,IAAA,aAAA,CAAc,UAAU,CAAA;AACxB,IAAa,UAAA,GAAA,WAAA,CAAY,UAAU,UAAU,CAAA;AAAA;AAEjD,EAAM,MAAA,qBAAA,GAAwB,IAAI,CAAgB,EAAA;AAClD,EAAsB,qBAAA,CAAA,MAAA,CAAO,gBAAiB,CAAA,OAAA,EAAS,MAAM;AACzD,IAAA,aAAA,CAAc,UAAU,CAAA;AAAA,GAC3B,CAAA;AACD,EAAkB,iBAAA,CAAA,gBAAA,CAAiB,SAAS,MAAM;AAC9C,IAAA,qBAAA,CAAsB,KAAM,EAAA;AAAA,GAC/B,CAAA;AACD,EAAQ,OAAA,CAAA,EAAA;AAAA,IACJ,OAAA;AAAA,IACA,MAAM;AACF,MAAA,qBAAA,CAAsB,KAAM,EAAA;AAAA,KAChC;AAAA,IACA,EAAE,MAAQ,EAAA,qBAAA,CAAsB,MAAO;AAAA,GAC3C;AACA,EAAA,OAAA,CAAQ,GAAG,SAAW,EAAA,gBAAA,EAAkB,EAAE,MAAQ,EAAA,qBAAA,CAAsB,QAAQ,CAAA;AAChF,EAAiD;AAC7C,IAAiB,gBAAA,EAAA;AAAA;AAmBrB,EAAO,OAAA;AAAA,IACH,GAAG,OAAA;AAAA,IACH,QAAQ,IAAM,EAAA;AACV,MAAI,IAAA,CAAC,qBAAsB,CAAA,MAAA,CAAO,OAAS,EAAA;AACvC,QAAiB,gBAAA,EAAA;AAAA;AAErB,MAAO,OAAA,OAAA,CAAQ,IAAK,CAAA,GAAG,IAAI,CAAA;AAAA;AAC/B,GACJ;AACJ;;;ACxEO,SAAS,iBAAiC,GAAA;AAC7C,EAAO,OAAA;AAAA,IACH,SAAS,EAAC;AAAA,IACV,gBAAkB,EAAA;AAAA,GACtB;AACJ;;;ACUO,SAAS,+BAEd,CAAA,aAAA,EAAgC,EAAE,0BAAA,EAA4B,aAAwC,EAAA;AACpG,EAAA,MAAM,OAAO,iBAAkB,EAAA;AAK/B,EAAA,SAAS,yBAA4B,GAAA;AACjC,IAAI,IAAA,IAAA,CAAK,OAAQ,CAAA,MAAA,GAAS,WAAa,EAAA;AAGnC,MAAA,IAAA,CAAK,gBAAmB,GAAA,EAAA;AACxB,MAAA;AAAA;AAEJ,IAAI,IAAA,eAAA;AACJ,IAAA,KAAA,IAAS,KAAK,CAAG,EAAA,EAAA,GAAK,IAAK,CAAA,OAAA,CAAQ,QAAQ,EAAM,EAAA,EAAA;AAC7C,MAAA,MAAM,iBAAiB,IAAK,CAAA,gBAAA,GAAmB,EAAK,GAAA,CAAA,IAAK,KAAK,OAAQ,CAAA,MAAA;AACtE,MAAM,MAAA,aAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAKF,IAAA,CAAK,QAAQ,aAAa;AAAA,OAAA;AAC9B,MACI,IAAA,aAAA,CAAc,oBAAoB,0BACjC,KAAA,CAAC,mBAAmB,eAAgB,CAAA,iBAAA,IAAqB,cAAc,iBAC1E,CAAA,EAAA;AACE,QAAkB,eAAA,GAAA;AAAA,UACd,SAAW,EAAA,aAAA;AAAA,UACX,mBAAmB,aAAc,CAAA;AAAA,SACrC;AAAA;AACJ;AAEJ,IAAK,IAAA,CAAA,gBAAA,GAAmB,iBAAiB,SAAa,IAAA,EAAA;AAAA;AAE1D,EAAA,OAAO,SAAS,iDAAA,CAAkD,EAAE,WAAA,EAAe,EAAA;AAC/E,IAAI,IAAA,SAAA;AACJ,IAAA,SAAS,gBAAmB,GAAA;AACxB,MAAA,MAAM,QAAQ,IAAK,CAAA,OAAA,CAAQ,SAAU,CAAA,CAAA,KAAA,KAAS,UAAU,SAAS,CAAA;AACjE,MAAK,IAAA,CAAA,OAAA,CAAQ,MAAO,CAAA,KAAA,EAAO,CAAC,CAAA;AAC5B,MAAA,SAAA,CAAU,OAAQ,EAAA;AAClB,MAA0B,yBAAA,EAAA;AAAA;AAE9B,IAAI,IAAA,IAAA,CAAK,qBAAqB,EAAI,EAAA;AAC9B,MAAM,MAAA,eAAA,GAAkB,IAAI,CAAgB,EAAA;AAC5C,MAAA,MAAM,oBAAoB,aAAc,CAAA,EAAE,WAAa,EAAA,eAAA,CAAgB,QAAQ,CAAA;AAC/E,MAAA,iBAAA,CACK,KAAK,CAAc,UAAA,KAAA;AAChB,QAAA,UAAA,CAAW,GAAG,OAAS,EAAA,gBAAA,EAAkB,EAAE,MAAQ,EAAA,eAAA,CAAgB,QAAQ,CAAA;AAAA,OAC9E,CACA,CAAA,KAAA,CAAM,gBAAgB,CAAA;AAC3B,MAAY,SAAA,GAAA;AAAA,QACR,OAAS,EAAA,iBAAA;AAAA,QACT,OAAU,GAAA;AACN,UAAA,eAAA,CAAgB,KAAM,EAAA;AAAA,SAC1B;AAAA,QACA,iBAAmB,EAAA;AAAA,OACvB;AACA,MAAK,IAAA,CAAA,OAAA,CAAQ,KAAK,SAAS,CAAA;AAAA,KACxB,MAAA;AACH,MAAY,SAAA,GAAA,IAAA,CAAK,OAAQ,CAAA,IAAA,CAAK,gBAAgB,CAAA;AAAA;AAYlD,IAAU,SAAA,CAAA,iBAAA,EAAA;AACV,IAAY,WAAA,CAAA,gBAAA,CAAiB,OAAS,EAAA,SAAS,eAAkB,GAAA;AAC7D,MAAU,SAAA,CAAA,iBAAA,EAAA;AACV,MAAI,IAAA,SAAA,CAAU,sBAAsB,CAAG,EAAA;AACnC,QAAiB,gBAAA,EAAA;AAAA,OACrB,MAAA,IAAW,IAAK,CAAA,gBAAA,KAAqB,EAAI,EAAA;AAErC,QAAK,IAAA,CAAA,gBAAA,EAAA;AACL,QAA0B,yBAAA,EAAA;AAAA;AAC9B,KACH,CAAA;AACD,IAA0B,yBAAA,EAAA;AAC1B,IAAA,OAAO,SAAU,CAAA,OAAA;AAAA,GACrB;AACJ;ACpGO,SAAS,gDACZ,OACyC,EAAA;AACzC,EAAO,OAAA,IAAA;AAAA,IACH,OAAA;AAAA,IACA,CAAK,CAAA,KAAA,+BAAA,CAAgC,CAAG,EAAA,IAAA,CAAK,KAAK,CAAA;AAAA,IAClD,CAAK,CAAA,KAAA,gCAAA,CAAiC,CAAG,EAAA,IAAA,CAAK,SAAS;AAAA,GAC3D;AACJ;ACLO,SAAS,sDACZ,OACyC,EAAA;AACzC,EAAOC,OAAAA,IAAAA;AAAA,IACH,OAAA;AAAA,IACA,CAAA,CAAA,KAAKC,+BAAgC,CAAA,CAAA,EAAG,oBAAoB,CAAA;AAAA,IAC5D,CAAA,CAAA,KAAKC,gCAAiC,CAAA,CAAA,EAAG,wBAAwB;AAAA,GACrE;AACJ;;;ACsBO,SAAS,kDACZ,MAC2E,EAAA;AAC3E,EAAA,OAAO,+CAAgD,CAAA;AAAA,IACnD,GAAG,MAAA;AAAA,IACH,cAAgB,EAAA;AAAA,GACnB,CAAA;AACL;AAKO,SAAS,4CACZ,MAC2E,EAAA;AAC3E,EAAA,OAAO,+CAAgD,CAAA;AAAA,IACnD,GAAG,MAAA;AAAA,IACH,cAAgB,EAAA;AAAA,GACnB,CAAA;AACL;AAEA,SAAS,gDACL,MAG2E,EAAA;AAC3E,EAAA,IAAI,SAAU,CAAA,IAAA,CAAK,MAAO,CAAA,GAAG,MAAM,KAAO,EAAA;AACtC,IAAA,MAAM,aAAgB,GAAA,MAAA,CAAO,GAAI,CAAA,KAAA,CAAM,WAAW,CAAA;AAClD,IAAA,MAAM,IAAI,YAAA;AAAA,MACN,aAAA,GACM,oFACW,aAAc,CAAA,CAAC,CAAC,CAC3B,kBAAA,CAAA,GAAA,CAAA,0CAAA,EAA6C,OAAO,GAAG,CAAA,aAAA;AAAA,KACjE;AAAA;AAEJ,EAAA,MAAM,EAAE,UAAA,EAAY,GAAG,IAAA,EAAS,GAAA,MAAA;AAChC,EAAA,MAAM,oCAAwC,GAAA,CAAC,EAAE,WAAA,EAAkB,KAAA;AAC/D,IAAA,OAAO,sBAAuB,CAAA;AAAA,MAC1B,GAAG,IAAA;AAAA,MACH,yBACI,MAAO,CAAA,uBAAA;AAAA,MAEP,MAAA;AAAA,MACJ,MAAQ,EAAA;AAAA,KACX,CAAA,CACI,IAAK,CAAA,MAAA,CAAO,cAAc,CAC1B,CAAA,IAAA;AAAA,MAAK,aACF,sCAAuC,CAAA;AAAA,QACnC,WAAA;AAAA,QACA,OAAA;AAAA,QACA,YAAY,UAAc,IAAA;AAAA,OAC7B;AAAA,KACL;AAAA,GACR;AACA,EAAA,OAAO,gCAAgC,oCAAsC,EAAA;AAAA,IACzE,4BACI,MAAO,CAAA,0BAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IASP,GAAA;AAAA,IACJ,WAAA,EAAa,OAAO,WAAe,IAAA;AAAA,GACtC,CAAA;AACL;AC/FO,SAAS,uDACZ,SACU,EAAA;AACV,EAAM,MAAA,KAAA,uBAAY,GAAwB,EAAA;AAC1C,EAAO,OAAA,SAAS,oDAAoD,MAAQ,EAAA;AACxE,IAAM,MAAA,EAAE,OAAS,EAAA,MAAA,EAAW,GAAA,MAAA;AAC5B,IAAA,MAAM,gCAAgC,mBAAoB,CAAA,CAAC,QAAQ,UAAY,EAAA,OAAA,CAAQ,MAAM,CAAC,CAAA;AAE9F,IAAI,IAAA,0BAAA,GAA6B,KAAM,CAAA,GAAA,CAAI,6BAA6B,CAAA;AACxE,IAAA,IAAI,CAAC,0BAA4B,EAAA;AAC7B,MAAM,MAAA,eAAA,GAAkB,IAAI,CAAgB,EAAA;AAC5C,MAAA,MAAM,uBAAuB,SAAU,CAAA;AAAA,QACnC,GAAG,MAAA;AAAA,QACH,QAAQ,eAAgB,CAAA;AAAA,OAC3B,CAAA;AACD,MAAA,oBAAA,CACK,KAAK,CAAiB,aAAA,KAAA;AACnB,QAAc,aAAA,CAAA,EAAA;AAAA,UACV,OAAA;AAAA,UACA,MAAM;AACF,YAAA,KAAA,CAAM,OAAO,6BAA6B,CAAA;AAC1C,YAAA,eAAA,CAAgB,KAAM,EAAA;AAAA,WAC1B;AAAA,UACA,EAAE,MAAQ,EAAA,eAAA,CAAgB,MAAO;AAAA,SACrC;AAAA,OACH,CACA,CAAA,KAAA,CAAM,MAAM;AAAA,OAAE,CAAA;AACnB,MAAM,KAAA,CAAA,GAAA;AAAA,QACF,6BAAA;AAAA,QACC,0BAA6B,GAAA;AAAA,UAC1B,eAAA;AAAA,UACA,oBAAA;AAAA,UACA,cAAgB,EAAA;AAAA;AACpB,OACJ;AAAA;AAEJ,IAA2B,0BAAA,CAAA,cAAA,EAAA;AAC3B,IAAO,MAAA,CAAA,gBAAA;AAAA,MACH,OAAA;AAAA,MACA,MAAM;AACF,QAA2B,0BAAA,CAAA,cAAA,EAAA;AAC3B,QAAI,IAAA,0BAAA,CAA2B,mBAAmB,CAAG,EAAA;AACjD,UAAA,cAAA,CAAe,MAAM;AACjB,YAAI,IAAA,0BAAA,CAA2B,mBAAmB,CAAG,EAAA;AACjD,cAAA,KAAA,CAAM,OAAO,6BAA6B,CAAA;AAC1C,cAAA,0BAAA,CAA2B,gBAAgB,KAAM,EAAA;AAAA;AACrD,WACH,CAAA;AAAA;AACL,OACJ;AAAA,MACA,EAAE,MAAA,EAAQ,0BAA2B,CAAA,eAAA,CAAgB,MAAO;AAAA,KAChE;AACA,IAAA,OAAO,0BAA2B,CAAA,oBAAA;AAAA,GACtC;AACJ;;;AC3CO,SAAS,sCAAuE,CAAA;AAAA,EACnF;AACJ,CAAwD,EAAA;AACpD,EAAOF,OAAAA,IAAAA;AAAA,IACH,iDAAA;AAAA,MACI;AAAA,KACJ;AAAA,IACA,CAAA,SAAA,KAAa,uDAAuD,SAAS;AAAA,GACjF;AACJ;AAEO,SAAS,kDAId,aAAgC,EAAA;AAC9B,EAAA,OAAQ,OAAO,EAAE,OAAS,EAAA,MAAA,EAAa,KAAA;AACnC,IAAA,MAAM,UAAU,MAAM,aAAA,CAAc,EAAE,WAAA,EAAa,QAAQ,CAAA;AAC3D,IAAA,OAAO,MAAM,OAAA,CAAQ,EAAE,OAAA,EAAS,QAAQ,CAAA;AAAA,GAC5C;AAOJ;;;ACpCA,SAAS,gCAAA,CACL,YACA,MACF,EAAA;AACE,EAAA,MAAM,YAAY,sCAAuC,CAAA;AAAA,IACrD,eAAe,iDAAkD,CAAA,EAAE,GAAG,MAAQ,EAAA,GAAA,EAAK,YAAY;AAAA,GAClG,CAAA;AACD,EAAA,OAAO,0CAAkE,SAAS,CAAA;AACtF;AAOO,SAAS,4BAAA,CACZ,YACA,MACF,EAAA;AACE,EAAO,OAAA,gCAAA,CAAyE,YAAY,MAAM,CAAA;AACtG;AAOO,SAAS,qCAAA,CACZ,YACA,MACF,EAAA;AACE,EAAO,OAAA,gCAAA;AAAA,IACH,UAAA;AAAA,IACA;AAAA,GACJ;AACJ;AAMO,SAAS,0CAGd,SAAuB,EAAA;AACrB,EAAA,OAAO,qBAAsB,CAAA;AAAA,IACzB,GAAA,EAAK,gCAAsC,gCAAgC,CAAA;AAAA,IAC3E;AAAA,GACH,CAAA;AACL","file":"index.native.mjs","sourcesContent":["import { safeCaptureStackTrace, SOLANA_ERROR__RPC__INTEGER_OVERFLOW, SolanaError } from '@solana/errors';\nimport type { KeyPath } from '@solana/rpc-transformers';\n\nexport function createSolanaJsonRpcIntegerOverflowError(\n methodName: string,\n keyPath: KeyPath,\n value: bigint,\n): SolanaError<typeof SOLANA_ERROR__RPC__INTEGER_OVERFLOW> {\n let argumentLabel = '';\n if (typeof keyPath[0] === 'number') {\n const argPosition = keyPath[0] + 1;\n const lastDigit = argPosition % 10;\n const lastTwoDigits = argPosition % 100;\n if (lastDigit == 1 && lastTwoDigits != 11) {\n argumentLabel = argPosition + 'st';\n } else if (lastDigit == 2 && lastTwoDigits != 12) {\n argumentLabel = argPosition + 'nd';\n } else if (lastDigit == 3 && lastTwoDigits != 13) {\n argumentLabel = argPosition + 'rd';\n } else {\n argumentLabel = argPosition + 'th';\n }\n } else {\n argumentLabel = `\\`${keyPath[0].toString()}\\``;\n }\n const path =\n keyPath.length > 1\n ? keyPath\n .slice(1)\n .map(pathPart => (typeof pathPart === 'number' ? `[${pathPart}]` : pathPart))\n .join('.')\n : undefined;\n const error = new SolanaError(SOLANA_ERROR__RPC__INTEGER_OVERFLOW, {\n argumentLabel,\n keyPath: keyPath as readonly (number | string | symbol)[],\n methodName,\n optionalPathLabel: path ? ` at path \\`${path}\\`` : '',\n value,\n ...(path !== undefined ? { path } : undefined),\n });\n safeCaptureStackTrace(error, createSolanaJsonRpcIntegerOverflowError);\n return error;\n}\n","import type { createSolanaRpcSubscriptionsApi } from '@solana/rpc-subscriptions-api';\n\nimport { createSolanaJsonRpcIntegerOverflowError } from './rpc-integer-overflow-error';\n\nexport const DEFAULT_RPC_SUBSCRIPTIONS_CONFIG: Partial<\n NonNullable<Parameters<typeof createSolanaRpcSubscriptionsApi>[0]>\n> = {\n defaultCommitment: 'confirmed',\n onIntegerOverflow(request, keyPath, value) {\n throw createSolanaJsonRpcIntegerOverflowError(request.methodName, keyPath, value);\n },\n};\n","export const AbortController = globalThis.AbortController;\nexport const EventTarget = globalThis.EventTarget;\n","import { isSolanaError, SOLANA_ERROR__RPC_SUBSCRIPTIONS__CHANNEL_CONNECTION_CLOSED } from '@solana/errors';\nimport { AbortController } from '@solana/event-target-impl';\nimport type { RpcSubscriptionsChannel } from '@solana/rpc-subscriptions-spec';\n\ntype Config<TChannel extends RpcSubscriptionsChannel<unknown, unknown>> = Readonly<{\n abortSignal: AbortSignal;\n channel: TChannel;\n intervalMs: number;\n}>;\n\nconst PING_PAYLOAD = {\n jsonrpc: '2.0',\n method: 'ping',\n} as const;\n\n/**\n * Given a {@link RpcSubscriptionsChannel}, will return a new channel that sends a ping message to\n * the inner channel if a message has not been sent or received in the last `intervalMs`. In web\n * browsers, this implementation sends no ping when the network is down, and sends a ping\n * immediately upon the network coming back up.\n */\nexport function getRpcSubscriptionsChannelWithAutoping<TChannel extends RpcSubscriptionsChannel<object, unknown>>({\n abortSignal: callerAbortSignal,\n channel,\n intervalMs,\n}: Config<TChannel>): TChannel {\n let intervalId: ReturnType<typeof setInterval> | undefined;\n function sendPing() {\n channel.send(PING_PAYLOAD).catch((e: unknown) => {\n if (isSolanaError(e, SOLANA_ERROR__RPC_SUBSCRIPTIONS__CHANNEL_CONNECTION_CLOSED)) {\n pingerAbortController.abort();\n }\n });\n }\n function restartPingTimer() {\n clearInterval(intervalId);\n intervalId = setInterval(sendPing, intervalMs);\n }\n const pingerAbortController = new AbortController();\n pingerAbortController.signal.addEventListener('abort', () => {\n clearInterval(intervalId);\n });\n callerAbortSignal.addEventListener('abort', () => {\n pingerAbortController.abort();\n });\n channel.on(\n 'error',\n () => {\n pingerAbortController.abort();\n },\n { signal: pingerAbortController.signal },\n );\n channel.on('message', restartPingTimer, { signal: pingerAbortController.signal });\n if (!__BROWSER__ || globalThis.navigator.onLine) {\n restartPingTimer();\n }\n if (__BROWSER__) {\n globalThis.addEventListener(\n 'offline',\n function handleOffline() {\n clearInterval(intervalId);\n },\n { signal: pingerAbortController.signal },\n );\n globalThis.addEventListener(\n 'online',\n function handleOnline() {\n sendPing();\n restartPingTimer();\n },\n { signal: pingerAbortController.signal },\n );\n }\n return {\n ...channel,\n send(...args) {\n if (!pingerAbortController.signal.aborted) {\n restartPingTimer();\n }\n return channel.send(...args);\n },\n };\n}\n","import { RpcSubscriptionsChannel } from '@solana/rpc-subscriptions-spec';\n\nexport type ChannelPoolEntry = {\n channel: PromiseLike<RpcSubscriptionsChannel<unknown, unknown>> | RpcSubscriptionsChannel<unknown, unknown>;\n readonly dispose: () => void;\n subscriptionCount: number;\n};\n\ntype ChannelPool = { readonly entries: ChannelPoolEntry[]; freeChannelIndex: number };\n\nexport function createChannelPool(): ChannelPool {\n return {\n entries: [],\n freeChannelIndex: -1,\n };\n}\n","import { AbortController } from '@solana/event-target-impl';\nimport { RpcSubscriptionsChannelCreator } from '@solana/rpc-subscriptions-spec';\n\nimport { ChannelPoolEntry, createChannelPool } from './rpc-subscriptions-channel-pool-internal';\n\ntype Config = Readonly<{\n maxSubscriptionsPerChannel: number;\n minChannels: number;\n}>;\n\n/**\n * Given a channel creator, will return a new channel creator with the following behavior.\n *\n * 1. When called, returns a {@link RpcSubscriptionsChannel}. Adds that channel to a pool.\n * 2. When called again, creates and returns new\n * {@link RpcSubscriptionChannel | RpcSubscriptionChannels} up to the number specified by\n * `minChannels`.\n * 3. When `minChannels` channels have been created, subsequent calls vend whichever existing\n * channel from the pool has the fewest subscribers, or the next one in rotation in the event of\n * a tie.\n * 4. Once all channels carry the number of subscribers specified by the number\n * `maxSubscriptionsPerChannel`, new channels in excess of `minChannel` will be created,\n * returned, and added to the pool.\n * 5. A channel will be destroyed once all of its subscribers' abort signals fire.\n */\nexport function getChannelPoolingChannelCreator<\n TChannelCreator extends RpcSubscriptionsChannelCreator<unknown, unknown>,\n>(createChannel: TChannelCreator, { maxSubscriptionsPerChannel, minChannels }: Config): TChannelCreator {\n const pool = createChannelPool();\n /**\n * This function advances the free channel index to the pool entry with the most capacity. It\n * sets the index to `-1` if all channels are full.\n */\n function recomputeFreeChannelIndex() {\n if (pool.entries.length < minChannels) {\n // Don't set the free channel index until the pool fills up; we want to keep creating\n // channels before we start rotating among them.\n pool.freeChannelIndex = -1;\n return;\n }\n let mostFreeChannel: Readonly<{ poolIndex: number; subscriptionCount: number }> | undefined;\n for (let ii = 0; ii < pool.entries.length; ii++) {\n const nextPoolIndex = (pool.freeChannelIndex + ii + 2) % pool.entries.length;\n const nextPoolEntry =\n // Start from the item two positions after the current item. This way, the\n // search will finish on the item after the current one. This ensures that, if\n // any channels tie for having the most capacity, the one that will be chosen is\n // the one immediately to the current one's right (wrapping around).\n pool.entries[nextPoolIndex];\n if (\n nextPoolEntry.subscriptionCount < maxSubscriptionsPerChannel &&\n (!mostFreeChannel || mostFreeChannel.subscriptionCount >= nextPoolEntry.subscriptionCount)\n ) {\n mostFreeChannel = {\n poolIndex: nextPoolIndex,\n subscriptionCount: nextPoolEntry.subscriptionCount,\n };\n }\n }\n pool.freeChannelIndex = mostFreeChannel?.poolIndex ?? -1;\n }\n return function getExistingChannelWithMostCapacityOrCreateChannel({ abortSignal }) {\n let poolEntry: ChannelPoolEntry;\n function destroyPoolEntry() {\n const index = pool.entries.findIndex(entry => entry === poolEntry);\n pool.entries.splice(index, 1);\n poolEntry.dispose();\n recomputeFreeChannelIndex();\n }\n if (pool.freeChannelIndex === -1) {\n const abortController = new AbortController();\n const newChannelPromise = createChannel({ abortSignal: abortController.signal });\n newChannelPromise\n .then(newChannel => {\n newChannel.on('error', destroyPoolEntry, { signal: abortController.signal });\n })\n .catch(destroyPoolEntry);\n poolEntry = {\n channel: newChannelPromise,\n dispose() {\n abortController.abort();\n },\n subscriptionCount: 0,\n };\n pool.entries.push(poolEntry);\n } else {\n poolEntry = pool.entries[pool.freeChannelIndex];\n }\n /**\n * A note about subscription counts.\n * Because of https://github.com/solana-labs/solana/pull/18943, two subscriptions for\n * materially the same notification will be coalesced on the server. This means they will be\n * assigned the same subscription id, and will occupy one subscription slot. We can't tell,\n * from here, whether a subscription will be treated in this way or not, so we\n * unconditionally increment the subscription count every time a subscription request is\n * made. This may result in subscription channels being treated as out-of-capacity when in\n * fact they are not.\n */\n poolEntry.subscriptionCount++;\n abortSignal.addEventListener('abort', function destroyConsumer() {\n poolEntry.subscriptionCount--;\n if (poolEntry.subscriptionCount === 0) {\n destroyPoolEntry();\n } else if (pool.freeChannelIndex !== -1) {\n // Back the free channel index up one position, and recompute it.\n pool.freeChannelIndex--;\n recomputeFreeChannelIndex();\n }\n });\n recomputeFreeChannelIndex();\n return poolEntry.channel;\n } as TChannelCreator;\n}\n","import { pipe } from '@solana/functional';\nimport {\n RpcSubscriptionsChannel,\n transformChannelInboundMessages,\n transformChannelOutboundMessages,\n} from '@solana/rpc-subscriptions-spec';\n\n/**\n * Given a {@link RpcSubscriptionsChannel}, will return a new channel that parses data published to\n * the `'message'` channel as JSON, and JSON-stringifies messages sent via the\n * {@link RpcSubscriptionsChannel.send | send(message)} method.\n */\nexport function getRpcSubscriptionsChannelWithJSONSerialization(\n channel: RpcSubscriptionsChannel<string, string>,\n): RpcSubscriptionsChannel<unknown, unknown> {\n return pipe(\n channel,\n c => transformChannelInboundMessages(c, JSON.parse),\n c => transformChannelOutboundMessages(c, JSON.stringify),\n );\n}\n","import { pipe } from '@solana/functional';\nimport { parseJsonWithBigInts, stringifyJsonWithBigints } from '@solana/rpc-spec-types';\nimport {\n RpcSubscriptionsChannel,\n transformChannelInboundMessages,\n transformChannelOutboundMessages,\n} from '@solana/rpc-subscriptions-spec';\n\n/**\n * Similarly, to {@link getRpcSubscriptionsChannelWithJSONSerialization}, this function will\n * stringify and parse JSON message to and from the given `string` channel. However, this function\n * parses any integer value as a `BigInt` in order to safely handle numbers that exceed the\n * JavaScript [`Number.MAX_SAFE_INTEGER`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/MAX_SAFE_INTEGER)\n * value.\n */\nexport function getRpcSubscriptionsChannelWithBigIntJSONSerialization(\n channel: RpcSubscriptionsChannel<string, string>,\n): RpcSubscriptionsChannel<unknown, unknown> {\n return pipe(\n channel,\n c => transformChannelInboundMessages(c, parseJsonWithBigInts),\n c => transformChannelOutboundMessages(c, stringifyJsonWithBigints),\n );\n}\n","import { createWebSocketChannel } from '@solana/rpc-subscriptions-channel-websocket';\nimport type { RpcSubscriptionsChannel } from '@solana/rpc-subscriptions-spec';\nimport type { ClusterUrl } from '@solana/rpc-types';\n\nimport { getRpcSubscriptionsChannelWithAutoping } from './rpc-subscriptions-autopinger';\nimport { getChannelPoolingChannelCreator } from './rpc-subscriptions-channel-pool';\nimport { RpcSubscriptionsChannelCreatorFromClusterUrl } from './rpc-subscriptions-clusters';\nimport { getRpcSubscriptionsChannelWithJSONSerialization } from './rpc-subscriptions-json';\nimport { getRpcSubscriptionsChannelWithBigIntJSONSerialization } from './rpc-subscriptions-json-bigint';\n\nexport type DefaultRpcSubscriptionsChannelConfig<TClusterUrl extends ClusterUrl> = Readonly<{\n /**\n * The number of milliseconds to wait since the last message sent or received over the channel\n * before sending a ping message to keep the channel open.\n */\n intervalMs?: number;\n /**\n * The number of subscribers that may share a channel before a new channel must be created.\n *\n * It is important that you set this to the maximum number of subscriptions that your RPC\n * provider recommends making over a single connection; the default is set deliberately low, so\n * as to comply with the restrictive limits of the public mainnet RPC node.\n *\n * @defaultValue 100\n */\n maxSubscriptionsPerChannel?: number;\n /** The number of channels to create before reusing a channel for a new subscription. */\n minChannels?: number;\n /**\n * The number of bytes of data to admit into the\n * [`WebSocket`](https://developer.mozilla.org/en-US/docs/Web/API/WebSocket) buffer before\n * buffering data on the client.\n */\n sendBufferHighWatermark?: number;\n /** The URL of the web socket server. Must use the `ws` or `wss` protocols. */\n url: TClusterUrl;\n}>;\n\n/**\n * Similar to {@link createDefaultRpcSubscriptionsChannelCreator} with some Solana-specific\n * defaults.\n *\n * For instance, it safely handles `BigInt` values in JSON messages since Solana RPC servers accept\n * and return integers larger than [`Number.MAX_SAFE_INTEGER`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/MAX_SAFE_INTEGER).\n */\nexport function createDefaultSolanaRpcSubscriptionsChannelCreator<TClusterUrl extends ClusterUrl>(\n config: DefaultRpcSubscriptionsChannelConfig<TClusterUrl>,\n): RpcSubscriptionsChannelCreatorFromClusterUrl<TClusterUrl, unknown, unknown> {\n return createDefaultRpcSubscriptionsChannelCreatorImpl({\n ...config,\n jsonSerializer: getRpcSubscriptionsChannelWithBigIntJSONSerialization,\n });\n}\n\n/**\n * Creates a function that returns new subscription channels when called.\n */\nexport function createDefaultRpcSubscriptionsChannelCreator<TClusterUrl extends ClusterUrl>(\n config: DefaultRpcSubscriptionsChannelConfig<TClusterUrl>,\n): RpcSubscriptionsChannelCreatorFromClusterUrl<TClusterUrl, unknown, unknown> {\n return createDefaultRpcSubscriptionsChannelCreatorImpl({\n ...config,\n jsonSerializer: getRpcSubscriptionsChannelWithJSONSerialization,\n });\n}\n\nfunction createDefaultRpcSubscriptionsChannelCreatorImpl<TClusterUrl extends ClusterUrl>(\n config: DefaultRpcSubscriptionsChannelConfig<TClusterUrl> & {\n jsonSerializer: (channel: RpcSubscriptionsChannel<string, string>) => RpcSubscriptionsChannel<unknown, unknown>;\n },\n): RpcSubscriptionsChannelCreatorFromClusterUrl<TClusterUrl, unknown, unknown> {\n if (/^wss?:/i.test(config.url) === false) {\n const protocolMatch = config.url.match(/^([^:]+):/);\n throw new DOMException(\n protocolMatch\n ? \"Failed to construct 'WebSocket': The URL's scheme must be either 'ws' or \" +\n `'wss'. '${protocolMatch[1]}:' is not allowed.`\n : `Failed to construct 'WebSocket': The URL '${config.url}' is invalid.`,\n );\n }\n const { intervalMs, ...rest } = config;\n const createDefaultRpcSubscriptionsChannel = (({ abortSignal }) => {\n return createWebSocketChannel({\n ...rest,\n sendBufferHighWatermark:\n config.sendBufferHighWatermark ??\n // Let 128KB of data into the WebSocket buffer before buffering it in the app.\n 131_072,\n signal: abortSignal,\n })\n .then(config.jsonSerializer)\n .then(channel =>\n getRpcSubscriptionsChannelWithAutoping({\n abortSignal,\n channel,\n intervalMs: intervalMs ?? 5_000,\n }),\n );\n }) as RpcSubscriptionsChannelCreatorFromClusterUrl<TClusterUrl, unknown, unknown>;\n return getChannelPoolingChannelCreator(createDefaultRpcSubscriptionsChannel, {\n maxSubscriptionsPerChannel:\n config.maxSubscriptionsPerChannel ??\n /**\n * A note about this default. The idea here is that, because some RPC providers impose\n * an upper limit on the number of subscriptions you can make per channel, we must\n * choose a number low enough to avoid hitting that limit. Without knowing what provider\n * a given person is using, or what their limit is, we have to choose the lowest of all\n * known limits. As of this writing (October 2024) that is the public mainnet RPC node\n * (api.mainnet-beta.solana.com) at 100 subscriptions.\n */\n 100,\n minChannels: config.minChannels ?? 1,\n });\n}\n","import { AbortController } from '@solana/event-target-impl';\nimport fastStableStringify from '@solana/fast-stable-stringify';\nimport { RpcSubscriptionsTransport } from '@solana/rpc-subscriptions-spec';\nimport { DataPublisher } from '@solana/subscribable';\n\ntype CacheEntry = {\n readonly abortController: AbortController;\n readonly dataPublisherPromise: Promise<DataPublisher>;\n numSubscribers: number;\n};\n\n/**\n * Given a {@link RpcSubscriptionsTransport}, will return a new transport that coalesces identical\n * subscriptions into a single subscription request to the server. The determination of whether a\n * subscription is the same as another is based on the `rpcRequest` returned by its\n * {@link RpcSubscriptionsPlan}. The subscription will only be aborted once all subscribers abort,\n * or there is an error.\n */\nexport function getRpcSubscriptionsTransportWithSubscriptionCoalescing<TTransport extends RpcSubscriptionsTransport>(\n transport: TTransport,\n): TTransport {\n const cache = new Map<string, CacheEntry>();\n return function rpcSubscriptionsTransportWithSubscriptionCoalescing(config) {\n const { request, signal } = config;\n const subscriptionConfigurationHash = fastStableStringify([request.methodName, request.params]);\n\n let cachedDataPublisherPromise = cache.get(subscriptionConfigurationHash);\n if (!cachedDataPublisherPromise) {\n const abortController = new AbortController();\n const dataPublisherPromise = transport({\n ...config,\n signal: abortController.signal,\n });\n dataPublisherPromise\n .then(dataPublisher => {\n dataPublisher.on(\n 'error',\n () => {\n cache.delete(subscriptionConfigurationHash);\n abortController.abort();\n },\n { signal: abortController.signal },\n );\n })\n .catch(() => {});\n cache.set(\n subscriptionConfigurationHash,\n (cachedDataPublisherPromise = {\n abortController,\n dataPublisherPromise,\n numSubscribers: 0,\n }),\n );\n }\n cachedDataPublisherPromise.numSubscribers++;\n signal.addEventListener(\n 'abort',\n () => {\n cachedDataPublisherPromise.numSubscribers--;\n if (cachedDataPublisherPromise.numSubscribers === 0) {\n queueMicrotask(() => {\n if (cachedDataPublisherPromise.numSubscribers === 0) {\n cache.delete(subscriptionConfigurationHash);\n cachedDataPublisherPromise.abortController.abort();\n }\n });\n }\n },\n { signal: cachedDataPublisherPromise.abortController.signal },\n );\n return cachedDataPublisherPromise.dataPublisherPromise;\n } as TTransport;\n}\n","import { pipe } from '@solana/functional';\nimport { RpcSubscriptionsChannelCreator, RpcSubscriptionsTransport } from '@solana/rpc-subscriptions-spec';\nimport { ClusterUrl } from '@solana/rpc-types';\n\nimport {\n RpcSubscriptionsChannelCreatorDevnet,\n RpcSubscriptionsChannelCreatorFromClusterUrl,\n RpcSubscriptionsChannelCreatorMainnet,\n RpcSubscriptionsChannelCreatorTestnet,\n RpcSubscriptionsTransportDevnet,\n RpcSubscriptionsTransportFromClusterUrl,\n RpcSubscriptionsTransportMainnet,\n RpcSubscriptionsTransportTestnet,\n} from './rpc-subscriptions-clusters';\nimport { getRpcSubscriptionsTransportWithSubscriptionCoalescing } from './rpc-subscriptions-coalescer';\n\nexport type DefaultRpcSubscriptionsTransportConfig<TClusterUrl extends ClusterUrl> = Readonly<{\n createChannel: RpcSubscriptionsChannelCreatorFromClusterUrl<TClusterUrl, unknown, unknown>;\n}>;\n\n/**\n * Creates a {@link RpcSubscriptionsTransport} with some default behaviours.\n *\n * The default behaviours include:\n * - Logic that coalesces multiple subscriptions for the same notifications with the same arguments\n * into a single subscription.\n *\n * @param config\n */\nexport function createDefaultRpcSubscriptionsTransport<TClusterUrl extends ClusterUrl>({\n createChannel,\n}: DefaultRpcSubscriptionsTransportConfig<TClusterUrl>) {\n return pipe(\n createRpcSubscriptionsTransportFromChannelCreator(\n createChannel,\n ) as RpcSubscriptionsTransport as RpcSubscriptionsTransportFromClusterUrl<TClusterUrl>,\n transport => getRpcSubscriptionsTransportWithSubscriptionCoalescing(transport),\n );\n}\n\nexport function createRpcSubscriptionsTransportFromChannelCreator<\n TChannelCreator extends RpcSubscriptionsChannelCreator<TOutboundMessage, TInboundMessage>,\n TInboundMessage,\n TOutboundMessage,\n>(createChannel: TChannelCreator) {\n return (async ({ execute, signal }) => {\n const channel = await createChannel({ abortSignal: signal });\n return await execute({ channel, signal });\n }) as TChannelCreator extends RpcSubscriptionsChannelCreatorDevnet<TOutboundMessage, TInboundMessage>\n ? RpcSubscriptionsTransportDevnet\n : TChannelCreator extends RpcSubscriptionsChannelCreatorTestnet<TOutboundMessage, TInboundMessage>\n ? RpcSubscriptionsTransportTestnet\n : TChannelCreator extends RpcSubscriptionsChannelCreatorMainnet<TOutboundMessage, TInboundMessage>\n ? RpcSubscriptionsTransportMainnet\n : RpcSubscriptionsTransport;\n}\n","import type { SolanaRpcSubscriptionsApi, SolanaRpcSubscriptionsApiUnstable } from '@solana/rpc-subscriptions-api';\nimport { createSolanaRpcSubscriptionsApi } from '@solana/rpc-subscriptions-api';\nimport {\n createSubscriptionRpc,\n RpcSubscriptionsApiMethods,\n type RpcSubscriptionsTransport,\n} from '@solana/rpc-subscriptions-spec';\nimport { ClusterUrl } from '@solana/rpc-types';\n\nimport { DEFAULT_RPC_SUBSCRIPTIONS_CONFIG } from './rpc-default-config';\nimport {\n createDefaultSolanaRpcSubscriptionsChannelCreator,\n DefaultRpcSubscriptionsChannelConfig,\n} from './rpc-subscriptions-channel';\nimport type { RpcSubscriptionsFromTransport } from './rpc-subscriptions-clusters';\nimport { createDefaultRpcSubscriptionsTransport } from './rpc-subscriptions-transport';\n\ntype Config<TClusterUrl extends ClusterUrl> = DefaultRpcSubscriptionsChannelConfig<TClusterUrl>;\n\nfunction createSolanaRpcSubscriptionsImpl<TClusterUrl extends ClusterUrl, TApi extends RpcSubscriptionsApiMethods>(\n clusterUrl: TClusterUrl,\n config?: Omit<Config<TClusterUrl>, 'url'>,\n) {\n const transport = createDefaultRpcSubscriptionsTransport({\n createChannel: createDefaultSolanaRpcSubscriptionsChannelCreator({ ...config, url: clusterUrl }),\n });\n return createSolanaRpcSubscriptionsFromTransport<typeof transport, TApi>(transport);\n}\n\n/**\n * Creates a {@link RpcSubscriptions} instance that exposes the Solana JSON RPC WebSocket API given\n * a cluster URL and some optional channel config. See\n * {@link createDefaultRpcSubscriptionsChannelCreator} for the shape of the channel config.\n */\nexport function createSolanaRpcSubscriptions<TClusterUrl extends ClusterUrl>(\n clusterUrl: TClusterUrl,\n config?: Omit<Config<TClusterUrl>, 'url'>,\n) {\n return createSolanaRpcSubscriptionsImpl<TClusterUrl, SolanaRpcSubscriptionsApi>(clusterUrl, config);\n}\n\n/**\n * Creates a {@link RpcSubscriptions} instance that exposes the Solana JSON RPC WebSocket API,\n * including its unstable methods, given a cluster URL and some optional channel config. See\n * {@link createDefaultRpcSubscriptionsChannelCreator} for the shape of the channel config.\n */\nexport function createSolanaRpcSubscriptions_UNSTABLE<TClusterUrl extends ClusterUrl>(\n clusterUrl: TClusterUrl,\n config?: Omit<Config<TClusterUrl>, 'url'>,\n) {\n return createSolanaRpcSubscriptionsImpl<TClusterUrl, SolanaRpcSubscriptionsApi & SolanaRpcSubscriptionsApiUnstable>(\n clusterUrl,\n config,\n );\n}\n\n/**\n * Creates a {@link RpcSubscriptions} instance that exposes the Solana JSON RPC WebSocket API given\n * the supplied {@link RpcSubscriptionsTransport}.\n */\nexport function createSolanaRpcSubscriptionsFromTransport<\n TTransport extends RpcSubscriptionsTransport,\n TApi extends RpcSubscriptionsApiMethods = SolanaRpcSubscriptionsApi,\n>(transport: TTransport) {\n return createSubscriptionRpc({\n api: createSolanaRpcSubscriptionsApi<TApi>(DEFAULT_RPC_SUBSCRIPTIONS_CONFIG),\n transport,\n }) as RpcSubscriptionsFromTransport<TApi, TTransport>;\n}\n"]}