diff --git a/.changeset/sweet-cobras-explode.md b/.changeset/sweet-cobras-explode.md
new file mode 100644
index 000000000000..aad5dd0ca72b
--- /dev/null
+++ b/.changeset/sweet-cobras-explode.md
@@ -0,0 +1,5 @@
+---
+'@solana/promises': patch
+---
+
+Created a package for dealing with JavaScript Promises, and copied the implementation of `getAbortablePromise` into it
diff --git a/packages/promises/.gitignore b/packages/promises/.gitignore
new file mode 100644
index 000000000000..849ddff3b7ec
--- /dev/null
+++ b/packages/promises/.gitignore
@@ -0,0 +1 @@
+dist/
diff --git a/packages/promises/.prettierignore b/packages/promises/.prettierignore
new file mode 100644
index 000000000000..849ddff3b7ec
--- /dev/null
+++ b/packages/promises/.prettierignore
@@ -0,0 +1 @@
+dist/
diff --git a/packages/promises/CHANGELOG.md b/packages/promises/CHANGELOG.md
new file mode 100644
index 000000000000..34d21dffc132
--- /dev/null
+++ b/packages/promises/CHANGELOG.md
@@ -0,0 +1 @@
+# @solana/promises
diff --git a/packages/promises/LICENSE b/packages/promises/LICENSE
new file mode 100644
index 000000000000..ec09953d3c23
--- /dev/null
+++ b/packages/promises/LICENSE
@@ -0,0 +1,20 @@
+Copyright (c) 2023 Solana Labs, Inc
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/packages/promises/README.md b/packages/promises/README.md
new file mode 100644
index 000000000000..8f09deb3c032
--- /dev/null
+++ b/packages/promises/README.md
@@ -0,0 +1,32 @@
+[![npm][npm-image]][npm-url]
+[![npm-downloads][npm-downloads-image]][npm-url]
+[![semantic-release][semantic-release-image]][semantic-release-url]
+
+[![code-style-prettier][code-style-prettier-image]][code-style-prettier-url]
+
+[code-style-prettier-image]: https://img.shields.io/badge/code_style-prettier-ff69b4.svg?style=flat-square
+[code-style-prettier-url]: https://github.com/prettier/prettier
+[npm-downloads-image]: https://img.shields.io/npm/dm/@solana/promises/rc.svg?style=flat
+[npm-image]: https://img.shields.io/npm/v/@solana/promises/rc.svg?style=flat
+[npm-url]: https://www.npmjs.com/package/@solana/promises/v/rc
+[semantic-release-image]: https://img.shields.io/badge/%20%20%F0%9F%93%A6%F0%9F%9A%80-semantic--release-e10079.svg
+[semantic-release-url]: https://github.com/semantic-release/semantic-release
+
+# @solana/promises
+
+This package contains helpers for using JavaScript promises.
+
+## Functions
+
+### `getAbortablePromise(promise, abortSignal?)`
+
+Rejects if the `abortSignal` is aborted before the promise settles. Resolves or rejects with the value of the promise otherwise.
+
+```ts
+const result = await getAbortablePromise(
+ // Resolves or rejects when `fetch` settles.
+ fetch('https://example.com/json').then(r => r.json()),
+ // ...unless it takes longer than 5 seconds, after which the `AbortSignal` is triggered.
+ AbortSignal.timeout(5000),
+);
+```
diff --git a/packages/promises/package.json b/packages/promises/package.json
new file mode 100644
index 000000000000..6bfab0e5cc85
--- /dev/null
+++ b/packages/promises/package.json
@@ -0,0 +1,76 @@
+{
+ "name": "@solana/promises",
+ "version": "2.0.0-rc.0",
+ "description": "Helpers for using JavaScript promises",
+ "exports": {
+ "browser": {
+ "import": "./dist/index.browser.mjs",
+ "require": "./dist/index.browser.cjs"
+ },
+ "node": {
+ "import": "./dist/index.node.mjs",
+ "require": "./dist/index.node.cjs"
+ },
+ "react-native": "./dist/index.native.mjs",
+ "types": "./dist/types/index.d.ts"
+ },
+ "browser": {
+ "./dist/index.node.cjs": "./dist/index.browser.cjs",
+ "./dist/index.node.mjs": "./dist/index.browser.mjs"
+ },
+ "main": "./dist/index.node.cjs",
+ "module": "./dist/index.node.mjs",
+ "react-native": "./dist/index.native.mjs",
+ "types": "./dist/types/index.d.ts",
+ "type": "commonjs",
+ "files": [
+ "./dist/"
+ ],
+ "sideEffects": false,
+ "keywords": [
+ "blockchain",
+ "solana",
+ "web3"
+ ],
+ "scripts": {
+ "compile:js": "tsup --config build-scripts/tsup.config.package.ts",
+ "compile:typedefs": "tsc -p ./tsconfig.declarations.json",
+ "dev": "jest -c ../../node_modules/@solana/test-config/jest-dev.config.ts --rootDir . --watch",
+ "prepublishOnly": "pnpm pkg delete devDependencies",
+ "publish-impl": "npm view $npm_package_name@$npm_package_version > /dev/null 2>&1 || pnpm publish --tag ${PUBLISH_TAG:-canary} --access public --no-git-checks",
+ "publish-packages": "pnpm prepublishOnly && pnpm publish-impl",
+ "style:fix": "pnpm eslint --fix src/* && pnpm prettier --log-level warn --ignore-unknown --write ./*",
+ "test:lint": "TERM_OVERRIDE=\"${TURBO_HASH:+dumb}\" TERM=${TERM_OVERRIDE:-$TERM} jest -c ../../node_modules/@solana/test-config/jest-lint.config.ts --rootDir . --silent",
+ "test:prettier": "TERM_OVERRIDE=\"${TURBO_HASH:+dumb}\" TERM=${TERM_OVERRIDE:-$TERM} jest -c ../../node_modules/@solana/test-config/jest-prettier.config.ts --rootDir . --silent",
+ "test:treeshakability:browser": "agadoo dist/index.browser.mjs",
+ "test:treeshakability:native": "agadoo dist/index.native.mjs",
+ "test:treeshakability:node": "agadoo dist/index.node.mjs",
+ "test:typecheck": "tsc --noEmit",
+ "test:unit:browser": "TERM_OVERRIDE=\"${TURBO_HASH:+dumb}\" TERM=${TERM_OVERRIDE:-$TERM} jest -c ../../node_modules/@solana/test-config/jest-unit.config.browser.ts --rootDir . --silent",
+ "test:unit:node": "TERM_OVERRIDE=\"${TURBO_HASH:+dumb}\" TERM=${TERM_OVERRIDE:-$TERM} jest -c ../../node_modules/@solana/test-config/jest-unit.config.node.ts --rootDir . --silent"
+ },
+ "author": "Solana Labs Maintainers ",
+ "license": "MIT",
+ "repository": {
+ "type": "git",
+ "url": "https://github.com/solana-labs/solana-web3.js"
+ },
+ "bugs": {
+ "url": "http://github.com/solana-labs/solana-web3.js/issues"
+ },
+ "browserslist": [
+ "supports bigint and not dead",
+ "maintained node versions"
+ ],
+ "peerDependencies": {
+ "typescript": ">=5"
+ },
+ "bundlewatch": {
+ "defaultCompression": "gzip",
+ "files": [
+ {
+ "path": "./dist/index*.js"
+ }
+ ]
+ }
+}
diff --git a/packages/react/src/__tests__/abortable-promise-test.ts b/packages/promises/src/__tests__/abortable-test.ts
similarity index 98%
rename from packages/react/src/__tests__/abortable-promise-test.ts
rename to packages/promises/src/__tests__/abortable-test.ts
index c76bb7c2634f..ef50b10a5e82 100644
--- a/packages/react/src/__tests__/abortable-promise-test.ts
+++ b/packages/promises/src/__tests__/abortable-test.ts
@@ -1,4 +1,4 @@
-import { getAbortablePromise } from '../abortable-promise';
+import { getAbortablePromise } from '../abortable';
describe('getAbortablePromise()', () => {
let promise: Promise;
diff --git a/packages/react/src/abortable-promise.ts b/packages/promises/src/abortable.ts
similarity index 100%
rename from packages/react/src/abortable-promise.ts
rename to packages/promises/src/abortable.ts
diff --git a/packages/promises/src/index.ts b/packages/promises/src/index.ts
new file mode 100644
index 000000000000..943d707d8d22
--- /dev/null
+++ b/packages/promises/src/index.ts
@@ -0,0 +1 @@
+export * from './abortable';
diff --git a/packages/promises/tsconfig.declarations.json b/packages/promises/tsconfig.declarations.json
new file mode 100644
index 000000000000..dc2d27bb09ff
--- /dev/null
+++ b/packages/promises/tsconfig.declarations.json
@@ -0,0 +1,10 @@
+{
+ "compilerOptions": {
+ "declaration": true,
+ "declarationMap": true,
+ "emitDeclarationOnly": true,
+ "outDir": "./dist/types"
+ },
+ "extends": "./tsconfig.json",
+ "include": ["src/index.ts", "src/types"]
+}
diff --git a/packages/promises/tsconfig.json b/packages/promises/tsconfig.json
new file mode 100644
index 000000000000..ff7e7c3a3c46
--- /dev/null
+++ b/packages/promises/tsconfig.json
@@ -0,0 +1,9 @@
+{
+ "$schema": "https://json.schemastore.org/tsconfig",
+ "compilerOptions": {
+ "lib": ["DOM", "ES2015"]
+ },
+ "display": "@solana/promises",
+ "extends": "../tsconfig/base.json",
+ "include": ["src"]
+}
diff --git a/packages/react/package.json b/packages/react/package.json
index 17a730390e53..ec03e3323f0d 100644
--- a/packages/react/package.json
+++ b/packages/react/package.json
@@ -69,6 +69,7 @@
"@solana/addresses": "workspace:*",
"@solana/errors": "workspace:*",
"@solana/keys": "workspace:*",
+ "@solana/promises": "workspace:*",
"@solana/signers": "workspace:*",
"@solana/transactions": "workspace:*",
"@solana/wallet-standard-features": "^1.2.0",
diff --git a/packages/react/src/useWalletAccountMessageSigner.ts b/packages/react/src/useWalletAccountMessageSigner.ts
index 36ea611a1b71..371fd0678ec8 100644
--- a/packages/react/src/useWalletAccountMessageSigner.ts
+++ b/packages/react/src/useWalletAccountMessageSigner.ts
@@ -1,11 +1,11 @@
import { Address, address } from '@solana/addresses';
import { SOLANA_ERROR__SIGNER__WALLET_MULTISIGN_UNIMPLEMENTED, SolanaError } from '@solana/errors';
import { SignatureBytes } from '@solana/keys';
+import { getAbortablePromise } from '@solana/promises';
import { MessageModifyingSigner, SignableMessage } from '@solana/signers';
import type { UiWalletAccount } from '@wallet-standard/ui';
import { useMemo } from 'react';
-import { getAbortablePromise } from './abortable-promise';
import { useSignMessage } from './useSignMessage';
/**
diff --git a/packages/react/src/useWalletAccountTransactionSendingSigner.ts b/packages/react/src/useWalletAccountTransactionSendingSigner.ts
index b2b8b1e5d126..15cab84ae287 100644
--- a/packages/react/src/useWalletAccountTransactionSendingSigner.ts
+++ b/packages/react/src/useWalletAccountTransactionSendingSigner.ts
@@ -1,12 +1,12 @@
import { address } from '@solana/addresses';
import { SOLANA_ERROR__SIGNER__WALLET_MULTISIGN_UNIMPLEMENTED, SolanaError } from '@solana/errors';
import { SignatureBytes } from '@solana/keys';
+import { getAbortablePromise } from '@solana/promises';
import { TransactionSendingSigner } from '@solana/signers';
import { getTransactionEncoder } from '@solana/transactions';
import { UiWalletAccount } from '@wallet-standard/ui';
import { useMemo, useRef } from 'react';
-import { getAbortablePromise } from './abortable-promise';
import { OnlySolanaChains } from './chain';
import { useSignAndSendTransaction } from './useSignAndSendTransaction';
diff --git a/packages/react/src/useWalletAccountTransactionSigner.ts b/packages/react/src/useWalletAccountTransactionSigner.ts
index 5bfe7af76a52..06591dd4b6cd 100644
--- a/packages/react/src/useWalletAccountTransactionSigner.ts
+++ b/packages/react/src/useWalletAccountTransactionSigner.ts
@@ -1,11 +1,11 @@
import { address } from '@solana/addresses';
import { SOLANA_ERROR__SIGNER__WALLET_MULTISIGN_UNIMPLEMENTED, SolanaError } from '@solana/errors';
+import { getAbortablePromise } from '@solana/promises';
import { TransactionModifyingSigner } from '@solana/signers';
import { getTransactionCodec } from '@solana/transactions';
import { UiWalletAccount } from '@wallet-standard/ui';
import { useMemo, useRef } from 'react';
-import { getAbortablePromise } from './abortable-promise';
import { OnlySolanaChains } from './chain';
import { useSignTransaction } from './useSignTransaction';
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index dc93d42ee488..e9b4504cdedd 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -647,6 +647,12 @@ importers:
specifier: workspace:*
version: link:../transaction-messages
+ packages/promises:
+ dependencies:
+ typescript:
+ specifier: '>=5'
+ version: 5.5.4
+
packages/react:
dependencies:
'@solana/addresses':
@@ -658,6 +664,9 @@ importers:
'@solana/keys':
specifier: workspace:*
version: link:../keys
+ '@solana/promises':
+ specifier: workspace:*
+ version: link:../promises
'@solana/signers':
specifier: workspace:*
version: link:../signers