BitGo / BitGoJS

BitGo JavaScript SDK
https://developers.bitgo.com/
Apache License 2.0
352 stars 272 forks source link

Create and sign a USDT (omni layer) transaction to help recover funds #676

Closed dannydeezy closed 3 years ago

dannydeezy commented 4 years ago

Feature Description

I would like to have a function in BitGoJS that helps me recover USDT that was sent to one of my wallet addresses.

Motivation

Often customers mistakenly send USDT to a bitcoin address, and there is currently not an easy way to recover these funds

Context

This script shows an implementation that constructs and signs this exact type of recovery with the User and Backup keys. You'll need to take the logic from that and fit it into BitGoJS

The new function should live in /modules/core/src/v2/coins/btc.ts and it should be something like this:

sendOmniToken(fromAddress: string, toAddress: string, tokenAmount: number, tokenId: number, fundingTxid?: string) : string

It should return a half-signed txhex, which the user can then submit to bitgo support to finalize the recovery

Feel free to ask questions. Some more info on Omni Layer transactions: The Omni Layer is a layer on top of Bitcoin, which allows you to create tokens (sometimes called "colored coins"). The original USDT (aka "Tether") was built on Bitcoin's omni layer. To send an Omni token from Address A to Address B, you create a Bitcoin transaction that takes a Bitcoin unspent from Address A and spends a small amount of BTC to Address B. Additionally, you add another OP_RETURN output on the transaction that has some custom Omni Data in it that basically says "Send X amount of Y token".

So in this situation, a customer accidentally has sent some 100 USDT to their bitcoin Address A, and they want to recover it and send the Tether to Address B. Here's how it will work:

First we ask the customer to send a small amount of BTC to Address A, about 0.0005 BTC is enough. The txid of this transaction is the fundingTxid. Now the user should be able to call your function like this. (Note the "tokenId" for USDT is "31").

const halfSigned = bitgo.coin('btc').sendOmniToken( <Address A>, <Address B>, 100, 31, <fundingTxid> )

halfSigned should be a valid transaction signed by the customer's user key.

This transaction will look like this: inputs: (fundingTxid):(vout of funds sent to Address A) outputs: 0.0000059 BTC to Address B 0.0003941 BTC to Address A (change) OP_RETURN output with Tether data.

For the OP_RETURN output, see lines 59-64 of this file

Sword-Smith commented 4 years ago

It is not clear to me how the private keys xprv should be fetched. I think I am able to create the correct unsigned transaction and from there, I guess modules/core/src/v2/coins/abstractUtxoCoin.ts/signTransaction should be called but it takes params.prv which is an extended private key, that I would guess I would have to get from a wallet object?

dannydeezy commented 4 years ago

Good question, I think you'll want to get the xprv using the wallet.getUserPrv function. This method will take in a keychain object and walletPassphrase string. You can get the keychain object with something like this:

const keychain = yield bitgo.coin('btc').keychains().get({ id: wallet._wallet.keys[0] });
Sword-Smith commented 4 years ago

I still have some problems getting this project to build on my setup (WSL, Windows, and in Arch Linux). The TypeScript transpilation fails with 32 errors.

There are so far four commits here. They should create an unsigned omni transaction from the specified address. If I manage to get the build working I should be able to progress further: https://github.com/Sword-Smith/BitGoJS/commits/master

gusan-one commented 3 years ago

Hello. I have the same issue and I'm not really familiar with omni and bitgo multisig system. Can I ask some questions? Does your script work? Can i use it to recover USDT from bitgo btc wallet? I can see that you are using encrypted backup key. Can I use same method if my backup key is at Coincover? As I understand I need 2 of 3 private keys to sign tx. One from field A(user key). The other is controlled by bitgo. And the third is either "backup encrypted key" or is controlled by Coincover, depending on wallet type. Is there a difference using your script what kind of wallet did I create on bitgo. Will be very grateful for any clarifications

Sword-Smith commented 3 years ago

As far as I can see, it should work. It hasn't been tested though and it's up to BitGo to get this tested + merged.

Ericrobert22 commented 3 years ago

Feature Description

I would like to have a function in BitGoJS that helps me recover USDT that was sent to one of my wallet addresses.

Motivation

Often customers mistakenly send USDT to a bitcoin address, and there is currently not an easy way to recover these funds

Context

This script shows an implementation that constructs and signs this exact type of recovery with the User and Backup keys. You'll need to take the logic from that and fit it into BitGoJS

The new function should live in /modules/core/src/v2/coins/btc.ts and it should be something like this:

sendOmniToken(fromAddress: string, toAddress: string, tokenAmount: number, tokenId: number, fundingTxid?: string) : string

It should return a half-signed txhex, which the user can then submit to bitgo support to finalize the recovery

Feel free to ask questions. Some more info on Omni Layer transactions: The Omni Layer is a layer on top of Bitcoin, which allows you to create tokens (sometimes called "colored coins"). The original USDT (aka "Tether") was built on Bitcoin's omni layer. To send an Omni token from Address A to Address B, you create a Bitcoin transaction that takes a Bitcoin unspent from Address A and spends a small amount of BTC to Address B. Additionally, you add another OP_RETURN output on the transaction that has some custom Omni Data in it that basically says "Send X amount of Y token".

So in this situation, a customer accidentally has sent some 100 USDT to their bitcoin Address A, and they want to recover it and send the Tether to Address B. Here's how it will work:

First we ask the customer to send a small amount of BTC to Address A, about 0.0005 BTC is enough. The txid of this transaction is the fundingTxid. Now the user should be able to call your function like this. (Note the "tokenId" for USDT is "31").

const halfSigned = bitgo.coin('btc').sendOmniToken( <Address A>, <Address B>, 100, 31, <fundingTxid> )

halfSigned should be a valid transaction signed by the customer's user key.

This transaction will look like this: inputs: (fundingTxid):(vout of funds sent to Address A) outputs: 0.0000059 BTC to Address B 0.0003941 BTC to Address A (change) OP_RETURN output with Tether data.

For the OP_RETURN output, see lines 59-64 of this file

Acehack1 on Instagram can get you back successfully. He actually got my bitcoin script for me

github-actions[bot] commented 3 years ago

This issue is stale because it has been open 30 days with no activity. Remove stale label or comment or this will be closed in 5 days.

github-actions[bot] commented 3 years ago

This issue was closed because it has been stalled for 5 days with no activity.