Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/deezy-inc/nosft-core
https://github.com/deezy-inc/nosft-core
Last synced: about 2 months ago
JSON representation
- Host: GitHub
- URL: https://github.com/deezy-inc/nosft-core
- Owner: deezy-inc
- Created: 2023-03-23T01:13:13.000Z (almost 2 years ago)
- Default Branch: main
- Last Pushed: 2024-07-09T20:11:13.000Z (6 months ago)
- Last Synced: 2024-10-29T15:44:58.561Z (2 months ago)
- Language: TypeScript
- Size: 272 KB
- Stars: 10
- Watchers: 0
- Forks: 7
- Open Issues: 4
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
# nosft-core
Tools for developing Nosft clients
### Project anatomy
```
lib
└ src → Application sources
└ app → Business logic
└ nosft → Nosft business logic to be exposed by library
└ deezy → Deezy business logic to be exposed by library
└ nostr → Nostr business logic to be exposed by library
...
└ config → Constants, Env variables, configuration settings in general
└ services → Application services layer
└ nosft → Nosft integration service
└ deezy → Deezy integration service
└ nostr → Nostr integration service
...
└ index.js → Main application entry point
└ README.md → Library documentation.
└ node_modules (generated) → NPM dependencies
└ test → Source folder for unit or functional tests
└ .editorconfig → EditorConfig helps maintain consistent coding styles for multiple developers working on the same project across various editors and IDEs
└ .env.sample → Sample of for the .env file
└ .gitignore → Files and folders to ignore by git
└ .npmrc → Npm configuration file
└ .prettierrc → Code formatter configuration
└ jest.config.js → Jest configuration file
└ tsconfig.json → Typescript configuration file
└ tslint.js → Typescript linter
└ build → Esbuild configuration file
└ justfile → just configuration file
```### Getting inscriptions
```js
import { getInscriptions, getAddress } from 'nosft-core';const addresss = await getAddress();
const inscriptionts = await getInscriptions(address);
```## Developing
1. Install [`just`](https://just.systems/)
2. `just -l`## Local build
```bash
npm run watch
```## Usage
You can install the Nosft Core SDK by running:
```bash
npm install nosft-core
```### Configuration
You can ovewrite any nosft configuration variable available by passing the object on initialization.
```js
import { Nosft } from 'nosft-core';const localConfig = {
// Overwrite RELAY URL
NOSTR_RELAY_URL: 'ws://localhost:7006',
};const nosft = Nosft({ ...localConfig });
```- [Here](https://github.com/deezy-inc/nosft-core/blob/main/src/config/config.ts#L84) you can see the list of available configurations.
### Wallet
The `connectWallet` method allows you to connect your wallet to the Nosft SDK:
```javascript
const { connectWallet } = nosft.wallet;
const pubKey = await connectWallet();
```### Address
You can retrieve address information using the `getAddressInfo` method:
```javascript
const { getAddressInfo } = nosft.address;
const addressInfo = await getAddressInfo(address);
```### UTXO
To check if a UTXO contains an inscription, use the `doesUtxoContainInscription` method. You can also retrieve the UTXOs associated with an address using the `getAddressUtxos` method:
```javascript
const { doesUtxoContainInscription, getAddressUtxos } = nosft.utxo;const hasInscription = await doesUtxoContainInscription(utxo);
const utxos = await getAddressUtxos(address);
```### Inscriptions
The `getInscription` method allows you to retrieve a specific inscription, and the `getInscriptions` method retrieves all available inscriptions:
```javascript
const { getInscription, getInscriptions } = nosft.inscriptions;const inscription = await getInscription(inscriptionId);
const inscriptions = await getInscriptions();
```### PSBT
You can use the `signPsbtMessage` method to sign a PSBT message, and the `broadcastTx` method to broadcast a transaction to the Bitcoin network. The `signAndBroadcastUtxo` method signs and broadcasts a UTXO transaction. The `getMetamaskSigner` method retrieves the signer used by Metamask, and the `signSigHash` method signs a message with the sighash flag:
```javascript
const { signPsbtMessage, broadcastTx, signAndBroadcastUtxo, getMetamaskSigner, signSigHash } = nosft.psbt;const signedPsbt = await signPsbtMessage(psbt, wallet);
await broadcastTx(signedTxHex);
const signedAndBroadcastedTx = await signAndBroadcastUtxo(wallet, psbt);
const metamaskSigner = await getMetamaskSigner();
const signedSigHash = await signSigHash(wallet, sighash);
```### Open Ordex
The `getAvailableUtxosWithoutInscription` method retrieves all available UTXOs without an inscription, and the `generatePSBTListingInscriptionForBuy` and `generatePSBTListingInscriptionForSale` methods generate PSBT messages for buying and selling, respectively. The `getOrderInformation` method retrieves order information:
```javascript
const {
getAvailableUtxosWithoutInscription,
generatePSBTListingInscriptionForBuy,
generatePSBTListingInscriptionForSale,
getOrderInformation,
} = nosft.openOrdex;
```## Usage
Here is the list of all required methods to create a client just like nosft.
```javascript
import { Nosft } from 'nosft-core';
import { localConfig } from '@lib/constants.config';const nosft = Nosft({ ...localConfig });
const { connectWallet } = nosft.wallet;
const { getAddressInfo } = nosft.address;
const { doesUtxoContainInscription, getAddressUtxos } = nosft.utxo;
const { getInscription, getInscriptions } = nosft.inscriptions;
const { signPsbtMessage, broadcastTx, signAndBroadcastUtxo, getMetamaskSigner, signSigHash } = nosft.psbt;
const { signAndBroadcastEvent, getNostrInscription, subscribeOrders, unsubscribeOrders } = nosft.nostr;const {
getAvailableUtxosWithoutInscription,
generatePSBTListingInscriptionForBuy,
generatePSBTListingInscriptionForSale,
getOrderInformation,
} = nosft.openOrdex;const {
shortenStr,
satsToFormattedDollarString,
fetchBitcoinPrice,
outputValue,
toXOnly,
sortUtxos,
parseOutpoint,
fetchRecommendedFee,
satToBtc,
calculateFee,
getTxHexById,
tweakSigner,
} = nosft.crypto;const { config } = nosft;
const {
NOSTR_RELAY_URL,
NOSTR_KIND_INSCRIPTION,
INSCRIPTION_SEARCH_DEPTH,
GITHUB_URL,
DEFAULT_FEE_RATE,
SENDS_ENABLED,
TESTNET,
ASSUMED_TX_BYTES,
ORDINALS_EXPLORER_URL,
RELAYS,
MAX_ONSALE,BITCOIN_PRICE_API_URL,
TURBO_API,
BLOCKSTREAM_API,
POOL_API_URL,
MEMPOOL_API_URL,
NETWORK,
DEFAULT_DERIV_PATH,
DUMMY_UTXO_VALUE,
FEE_LEVEL,
TAPROOT_MESSAGE,
} = config;export default nosft;
export {
getAddressInfo,
connectWallet,// Crypto
shortenStr,
satsToFormattedDollarString,
fetchBitcoinPrice,
outputValue,
toXOnly,
sortUtxos,
parseOutpoint,
fetchRecommendedFee,
satToBtc,
calculateFee,
getTxHexById,
tweakSigner,// utxo
doesUtxoContainInscription,
getAddressUtxos,// inscriptions
getInscription,
getInscriptions,// psbt
signPsbtMessage,
broadcastTx,
signAndBroadcastUtxo,
getMetamaskSigner,
signSigHash,// open ordex
getAvailableUtxosWithoutInscription,
generatePSBTListingInscriptionForBuy,
generatePSBTListingInscriptionForSale,
getOrderInformation,// nostr
signAndBroadcastEvent,
getNostrInscription,
subscribeOrders,
unsubscribeOrders,// Config variables
TAPROOT_MESSAGE,
NOSTR_RELAY_URL,
NOSTR_KIND_INSCRIPTION,
INSCRIPTION_SEARCH_DEPTH,
GITHUB_URL,
DEFAULT_FEE_RATE,
SENDS_ENABLED,
TESTNET,
ASSUMED_TX_BYTES,
ORDINALS_EXPLORER_URL,
RELAYS,
MAX_ONSALE,
BITCOIN_PRICE_API_URL,
TURBO_API,
BLOCKSTREAM_API,
POOL_API_URL,
MEMPOOL_API_URL,
NETWORK,
DEFAULT_DERIV_PATH,
DUMMY_UTXO_VALUE,
FEE_LEVEL,
};
```### Get owned ordinals
This function returns all of the user utxo's, if you only need inscription, filter them
/to the ones that has inscriptionId defined.```javascript
import { connectWallet, getInscriptions } from '@services/nosft';const pubKey = await connectWallet(metamask);
const utxos = await getInscriptions(nostrAddress);
```### Get specific inscription
```javascript
const inscriptionId = 'YOUR INSCRIPTION ID';
const { inscription, collection } = await getInscription(slug);
```### Get list of listed inscriptions in nostr
```javascript
import { subscribeOrders as subscribeNosftOrders, unsubscribeOrders } from '@services/nosft';const callback = (err, data) => { ... } // your callback
const orderEvent = (err, event) => {
if (err) {
callback(err);
} else {
callback(null, event);
}
};// Returns subs
const subscriptionOrders = subscribeNosftOrders({ callback: orderEvent, limit });// To unsuscribe
if (subscriptionOrders) {
unsubscribeOrders();
subscriptionOrders.unsub();
subscriptionOrders = null;
}
```## Sell your own inscription
```javascript
import {
shortenStr,
fetchBitcoinPrice,
satsToFormattedDollarString,
generatePSBTListingInscriptionForSale,
signAndBroadcastEvent,
} from '@services/nosft';const psbt = await generatePSBTListingInscriptionForSale({
utxo,
paymentAddress: destinationBtcAddress,
price: ordinalValue,
});const signedPsbt = await signPsbtMessage(psbt);
await signAndBroadcastEvent({
utxo,
ordinalValue,
signedPsbt: signedPsbt.toBase64(),
pubkey: nostrPublicKey,
});
```### Buy an inscription
For buying we need to get the signed psbt from nostr first.
To get the inscription and nostr information we can do as follows```javascript
import { getAddressInfo, getInscription, getNostrInscription } from '@services/nosft';const fetchInscription = async (inscriptionId) => {
const { inscription: _inscription, collection: _collection } = await getInscription(inscriptionId);
setInscription(_inscription);
setCollection(_collection);
};const inscription = await fetchInscription(inscriptionId);
const nostr = await getNostrInscription(inscriptionId);
```Once we have the inscription and nostr data we can continue with the buy.
```javascript
import {
signPsbtMessage,
broadcastTx,
getAvailableUtxosWithoutInscription,
generatePSBTListingInscriptionForBuy,
} from '@services/nosft';// If buying with BTC, user should get at least 2 dummy utxos
const updatePayerAddress = async (address) => {
try {
const { selectedUtxos: _selectedUtxos, dummyUtxos: _dummyUtxos } = await getAvailableUtxosWithoutInscription({
address,
price: utxo.value,
});if (_dummyUtxos.length < 2) {
throw new Error('No dummy UTXOs found. Please create them before continuing.');
}setSelectedUtxos(_selectedUtxos);
setDummyUtxos(_dummyUtxos);
} catch (e) {
setSelectedUtxos([]);
throw e;
}
};const buy = async () => {
try {
await updatePayerAddress(destinationBtcAddress);
} catch (e) {
setIsBtcInputAddressValid(false);
toast.error(e.message);
return;
}try {
const sellerSignedPsbt = bitcoin.Psbt.fromBase64(nostr.content, { network: NETWORK });const psbt = await generatePSBTListingInscriptionForBuy({
payerAddress: destinationBtcAddress,
receiverAddress: destinationBtcAddress,
price: nostr.value,
paymentUtxos: selectedUtxos,
dummyUtxos,
sellerSignedPsbt,
inscription: utxo,
});const tx = await signPsbtMessage(psbt);
const txId = await broadcastTx(tx);
} catch (e) {
toast.error(e.message);
}
};
```## License
# Public domain.