Skip to content

Commit

Permalink
Include mints to recipients as transfers in the forest
Browse files Browse the repository at this point in the history
  • Loading branch information
dankelleher committed Apr 22, 2023
1 parent f99922a commit 23a531b
Show file tree
Hide file tree
Showing 6 changed files with 44 additions and 9 deletions.
3 changes: 2 additions & 1 deletion packages/app/src/api/db.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ const buildTransferRecord = (transfer: TransferResponse): Transfer => ({
const buildMintRecord = (mint: MintResponse): Mint => ({
timestamp: new Date(mint.timestamp),
recipient: new PublicKey(mint.recipient),
sender: mint.sender !== undefined ? new PublicKey(mint.sender) : undefined,
amount: mint.amount,
});
const getDBData = async <T>(
Expand Down Expand Up @@ -60,7 +61,7 @@ const getDBData = async <T>(
}).then(async (resp) => resp.json());
};
export const getAccountMints = async (address: PublicKey): Promise<Mint[]> =>
getDBData<MintResponse>("mints", ["recipient"], address)
getDBData<MintResponse>("mints", ["sender", "recipient"], address)
.then((resp) => resp.documents)
.then((mints) => mints.map(buildMintRecord));
export const getAccountTransfers = async (
Expand Down
19 changes: 15 additions & 4 deletions packages/app/src/api/forest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ import {
getGsolBalance,
getLockedBalance,
getTotals,
mintsToSelf,
mintsWithRecipientsAsTransfers,
prune,
} from "./util";
import { type SunriseClientWrapper } from "../common/sunriseClientWrapper";
Expand Down Expand Up @@ -104,20 +106,29 @@ export class ForestService {
getAccountTransfers(address),
]
);
const received = transfers.filter((t) => t.recipient.equals(address));
const sent = transfers.filter((t) => t.sender.equals(address));

// get all transfers including gsol minted directly into a recipient's account
const enrichedTransfers = [
...transfers,
...mintsWithRecipientsAsTransfers(mints),
];
const filteredMints = mintsToSelf(mints);
const received = enrichedTransfers.filter((t) =>
t.recipient.equals(address)
);
const sent = enrichedTransfers.filter((t) => t.sender.equals(address));
const totals = getTotals(
currentBalance,
lockedBalance,
mints,
filteredMints,
received,
sent
);
const startDate = earliest([...mints, ...transfers]);

return {
address,
mints,
mints: filteredMints,
sent,
received,
totals,
Expand Down
4 changes: 3 additions & 1 deletion packages/app/src/api/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { type PublicKey } from "@solana/web3.js";

export interface MintResponse {
timestamp: string;
sender?: string; // the wallet that pays for the mint (assume = the recipient if missing)
recipient: string;
amount: number;
}
Expand All @@ -19,7 +20,8 @@ export interface MongoResponse<T> {

export interface Mint {
timestamp: Date;
recipient: PublicKey;
sender?: PublicKey; // the wallet that pays for the mint (assume = the recipient if missing)
recipient: PublicKey; // the wallet that receives the minted gSOL
amount: number;
}

Expand Down
21 changes: 21 additions & 0 deletions packages/app/src/api/util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,27 @@ export const filterFirstTransfersForSenderAndRecipient = (
return Object.values(firstTransfers);
};

const isMintTransfer = (mint: Mint): mint is Required<Mint> =>
mint.sender !== undefined && !mint.sender.equals(mint.recipient);

/**
* Find all mints for which the recipient is not the sender and return them as transfers
* This ensures that transferred gSOL and gSOL that is minted directly into someone else's account
* are treated the same way
*/
export const mintsWithRecipientsAsTransfers = (mints: Mint[]): Transfer[] => {
return mints.filter(isMintTransfer).map((mint) => ({
amount: mint.amount,
sender: mint.sender,
recipient: mint.recipient,
timestamp: mint.timestamp,
}));
};
export const mintsToSelf = (mints: Mint[]): Mint[] =>
mints.filter(
(mint) => mint.sender === undefined || mint.sender.equals(mint.recipient)
);

export const prune = (forest: Forest): Forest => {
const seen: string[] = [];
// if a tree node is in the seen array, it's a duplicate, remove it.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,7 @@ const SendGSolModal: FC<ModalProps & SendGSolModalProps> = ({
{currency === "SOL" ? (
<div className="mt-2 mb-4 text-sm text-grey">
<MdInfo className="inline stroke-grey" />
SOL gets staked and send as gSOL
SOL will be staked and sent as gSOL
</div>
) : null}
<div className="">
Expand Down
4 changes: 2 additions & 2 deletions packages/app/src/tipjar/components/DonatableArtistNFT.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -71,8 +71,8 @@ export const DonatableArtistNFT: FC<Props> = ({ query, onDonate }) => {
Recognition for those who deserve it.
</h1>
<p>
Received an Earth Day NFT? Drop some SOL in your artist&apos;s wallet.
DRiP is all about free art, so there&apos;s no obligation.
Received an Earth Day NFT? Drop some SOL in your artist&apos;s
wallet. DRiP is all about free art, so there&apos;s no obligation.
Every lamport is appreciated!
</p>
</div>
Expand Down

0 comments on commit 23a531b

Please sign in to comment.