satisitics with invoice & withdrawal
This commit is contained in:
		
							parent
							
								
									8cdeb18216
								
							
						
					
					
						commit
						06f5ed731e
					
				@ -2,6 +2,7 @@ import { createInvoice, decodePaymentRequest, subscribeToPayViaRequest } from 'l
 | 
				
			|||||||
import { UserInputError, AuthenticationError } from 'apollo-server-micro'
 | 
					import { UserInputError, AuthenticationError } from 'apollo-server-micro'
 | 
				
			||||||
import serialize from './serial'
 | 
					import serialize from './serial'
 | 
				
			||||||
import { decodeCursor, LIMIT, nextCursorEncoded } from '../../lib/cursor'
 | 
					import { decodeCursor, LIMIT, nextCursorEncoded } from '../../lib/cursor'
 | 
				
			||||||
 | 
					import lnpr from 'bolt11'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export default {
 | 
					export default {
 | 
				
			||||||
  Query: {
 | 
					  Query: {
 | 
				
			||||||
@ -50,19 +51,19 @@ export default {
 | 
				
			|||||||
    },
 | 
					    },
 | 
				
			||||||
    walletHistory: async (parent, { cursor }, { me, models, lnd }) => {
 | 
					    walletHistory: async (parent, { cursor }, { me, models, lnd }) => {
 | 
				
			||||||
      const decodedCursor = decodeCursor(cursor)
 | 
					      const decodedCursor = decodeCursor(cursor)
 | 
				
			||||||
      // if (!me) {
 | 
					      if (!me) {
 | 
				
			||||||
      //   throw new AuthenticationError('you must be logged in')
 | 
					        throw new AuthenticationError('you must be logged in')
 | 
				
			||||||
      // }
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      // TODO
 | 
					      // TODO
 | 
				
			||||||
      // 1. union invoices and withdrawals
 | 
					      // 1. union invoices and withdrawals (check)
 | 
				
			||||||
      // 2. add to union spending and receiving
 | 
					      // 2. add to union spending and receiving
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      const history = await models.$queryRaw(`
 | 
					      let history = await models.$queryRaw(`
 | 
				
			||||||
      (SELECT id, bolt11, created_at as "createdAt",
 | 
					      (SELECT id, bolt11, created_at as "createdAt",
 | 
				
			||||||
        "msatsReceived" as msats, NULL as "msatsFee",
 | 
					        COALESCE("msatsReceived", "msatsRequested") as msats, NULL as "msatsFee",
 | 
				
			||||||
        CASE WHEN "confirmedAt" IS NOT NULL THEN 'CONFIRMED'
 | 
					        CASE WHEN "confirmedAt" IS NOT NULL THEN 'CONFIRMED'
 | 
				
			||||||
             WHEN "expiresAt" IS NOT NULL THEN 'EXPIRED'
 | 
					             WHEN "expiresAt" <= $2 THEN 'EXPIRED'
 | 
				
			||||||
             WHEN cancelled THEN 'CANCELLED'
 | 
					             WHEN cancelled THEN 'CANCELLED'
 | 
				
			||||||
             ELSE 'PENDING' END as status,
 | 
					             ELSE 'PENDING' END as status,
 | 
				
			||||||
        'invoice' as type
 | 
					        'invoice' as type
 | 
				
			||||||
@ -86,7 +87,31 @@ export default {
 | 
				
			|||||||
        LIMIT ${LIMIT}+$3)
 | 
					        LIMIT ${LIMIT}+$3)
 | 
				
			||||||
      ORDER BY "createdAt" DESC
 | 
					      ORDER BY "createdAt" DESC
 | 
				
			||||||
      OFFSET $3
 | 
					      OFFSET $3
 | 
				
			||||||
      LIMIT ${LIMIT}`, 624, decodedCursor.time, decodedCursor.offset)
 | 
					      LIMIT ${LIMIT}`, me.id, decodedCursor.time, decodedCursor.offset)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      history = history.map(f => {
 | 
				
			||||||
 | 
					        if (f.bolt11) {
 | 
				
			||||||
 | 
					          const inv = lnpr.decode(f.bolt11)
 | 
				
			||||||
 | 
					          if (inv) {
 | 
				
			||||||
 | 
					            const { tags } = inv
 | 
				
			||||||
 | 
					            for (const tag of tags) {
 | 
				
			||||||
 | 
					              if (tag.tagName === 'description') {
 | 
				
			||||||
 | 
					                f.description = tag.data
 | 
				
			||||||
 | 
					                break
 | 
				
			||||||
 | 
					              }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        switch (f.type) {
 | 
				
			||||||
 | 
					          case 'withdrawal':
 | 
				
			||||||
 | 
					            f.msats *= -1
 | 
				
			||||||
 | 
					            break
 | 
				
			||||||
 | 
					          default:
 | 
				
			||||||
 | 
					            break
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return f
 | 
				
			||||||
 | 
					      })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      return {
 | 
					      return {
 | 
				
			||||||
        cursor: history.length === LIMIT ? nextCursorEncoded(decodedCursor) : null,
 | 
					        cursor: history.length === LIMIT ? nextCursorEncoded(decodedCursor) : null,
 | 
				
			||||||
 | 
				
			|||||||
@ -41,12 +41,13 @@ export default gql`
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  type Fact {
 | 
					  type Fact {
 | 
				
			||||||
    id: ID!
 | 
					    id: ID!
 | 
				
			||||||
    bolt11: String!
 | 
					    bolt11: String
 | 
				
			||||||
    createdAt: String!
 | 
					    createdAt: String!
 | 
				
			||||||
    msats: Int!
 | 
					    msats: Int!
 | 
				
			||||||
    msatsFee: Int!
 | 
					    msatsFee: Int
 | 
				
			||||||
    status: String!
 | 
					    status: String!
 | 
				
			||||||
    type: String!
 | 
					    type: String!
 | 
				
			||||||
 | 
					    description: String
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  type History {
 | 
					  type History {
 | 
				
			||||||
 | 
				
			|||||||
@ -32,6 +32,7 @@ export default function UserHeader ({ user }) {
 | 
				
			|||||||
  const [setName] = useMutation(NAME_MUTATION)
 | 
					  const [setName] = useMutation(NAME_MUTATION)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const Satistics = () => <h1 className='mb-0'><small className='text-success'>{user.sats} sats \ {user.stacked} stacked</small></h1>
 | 
					  const Satistics = () => <h1 className='mb-0'><small className='text-success'>{user.sats} sats \ {user.stacked} stacked</small></h1>
 | 
				
			||||||
 | 
					  const isMe = me?.name === user.name
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const UserSchema = Yup.object({
 | 
					  const UserSchema = Yup.object({
 | 
				
			||||||
    name: Yup.string()
 | 
					    name: Yup.string()
 | 
				
			||||||
@ -104,7 +105,7 @@ export default function UserHeader ({ user }) {
 | 
				
			|||||||
          : (
 | 
					          : (
 | 
				
			||||||
            <div className='d-flex align-items-center'>
 | 
					            <div className='d-flex align-items-center'>
 | 
				
			||||||
              <h2 className='mb-0'>@{user.name}</h2>
 | 
					              <h2 className='mb-0'>@{user.name}</h2>
 | 
				
			||||||
              {me?.name === user.name &&
 | 
					              {isMe &&
 | 
				
			||||||
                <Button variant='link' onClick={() => setEditting(true)}>edit nym</Button>}
 | 
					                <Button variant='link' onClick={() => setEditting(true)}>edit nym</Button>}
 | 
				
			||||||
            </div>
 | 
					            </div>
 | 
				
			||||||
            )}
 | 
					            )}
 | 
				
			||||||
@ -129,11 +130,12 @@ export default function UserHeader ({ user }) {
 | 
				
			|||||||
            <Nav.Link>{user.ncomments} comments</Nav.Link>
 | 
					            <Nav.Link>{user.ncomments} comments</Nav.Link>
 | 
				
			||||||
          </Link>
 | 
					          </Link>
 | 
				
			||||||
        </Nav.Item>
 | 
					        </Nav.Item>
 | 
				
			||||||
        {/* <Nav.Item>
 | 
					        {isMe &&
 | 
				
			||||||
          <Link href={'/' + user.name + '/sativity'} passHref>
 | 
					          <Nav.Item>
 | 
				
			||||||
 | 
					            <Link href='/satistics' passHref>
 | 
				
			||||||
              <Nav.Link>satistics</Nav.Link>
 | 
					              <Nav.Link>satistics</Nav.Link>
 | 
				
			||||||
            </Link>
 | 
					            </Link>
 | 
				
			||||||
        </Nav.Item> */}
 | 
					          </Nav.Item>}
 | 
				
			||||||
      </Nav>
 | 
					      </Nav>
 | 
				
			||||||
    </>
 | 
					    </>
 | 
				
			||||||
  )
 | 
					  )
 | 
				
			||||||
 | 
				
			|||||||
@ -24,6 +24,24 @@ export const WITHDRAWL = gql`
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
  }`
 | 
					  }`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const WALLET_HISTORY = gql`
 | 
				
			||||||
 | 
					  query WalletHistory($cursor: String) {
 | 
				
			||||||
 | 
					    walletHistory(cursor: $cursor) {
 | 
				
			||||||
 | 
					      facts {
 | 
				
			||||||
 | 
					        id
 | 
				
			||||||
 | 
					        type
 | 
				
			||||||
 | 
					        createdAt
 | 
				
			||||||
 | 
					        msats
 | 
				
			||||||
 | 
					        msatsFee
 | 
				
			||||||
 | 
					        status
 | 
				
			||||||
 | 
					        type
 | 
				
			||||||
 | 
					        description
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      cursor
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const CREATE_WITHDRAWL = gql`
 | 
					export const CREATE_WITHDRAWL = gql`
 | 
				
			||||||
  mutation createWithdrawl($invoice: String!, $maxFee: Int!) {
 | 
					  mutation createWithdrawl($invoice: String!, $maxFee: Int!) {
 | 
				
			||||||
    createWithdrawl(invoice: $invoice, maxFee: $maxFee) {
 | 
					    createWithdrawl(invoice: $invoice, maxFee: $maxFee) {
 | 
				
			||||||
 | 
				
			|||||||
@ -64,6 +64,19 @@ export default function getApolloClient () {
 | 
				
			|||||||
                  lastChecked: incoming.lastChecked
 | 
					                  lastChecked: incoming.lastChecked
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
              }
 | 
					              }
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            walletHistory: {
 | 
				
			||||||
 | 
					              keyArgs: false,
 | 
				
			||||||
 | 
					              merge (existing, incoming) {
 | 
				
			||||||
 | 
					                if (isFirstPage(incoming.cursor, existing?.facts)) {
 | 
				
			||||||
 | 
					                  return incoming
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                return {
 | 
				
			||||||
 | 
					                  cursor: incoming.cursor,
 | 
				
			||||||
 | 
					                  facts: [...(existing?.facts || []), ...incoming.facts]
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					              }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
          }
 | 
					          }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										112
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										112
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							@ -14,6 +14,7 @@
 | 
				
			|||||||
        "async-retry": "^1.3.1",
 | 
					        "async-retry": "^1.3.1",
 | 
				
			||||||
        "babel-plugin-inline-react-svg": "^2.0.1",
 | 
					        "babel-plugin-inline-react-svg": "^2.0.1",
 | 
				
			||||||
        "bech32": "^2.0.0",
 | 
					        "bech32": "^2.0.0",
 | 
				
			||||||
 | 
					        "bolt11": "^1.3.4",
 | 
				
			||||||
        "bootstrap": "^4.6.0",
 | 
					        "bootstrap": "^4.6.0",
 | 
				
			||||||
        "clipboard-copy": "^4.0.1",
 | 
					        "clipboard-copy": "^4.0.1",
 | 
				
			||||||
        "domino": "^2.1.6",
 | 
					        "domino": "^2.1.6",
 | 
				
			||||||
@ -910,6 +911,14 @@
 | 
				
			|||||||
        "@types/node": "*"
 | 
					        "@types/node": "*"
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
					    "node_modules/@types/bn.js": {
 | 
				
			||||||
 | 
					      "version": "4.11.6",
 | 
				
			||||||
 | 
					      "resolved": "https://registry.npmjs.org/@types/bn.js/-/bn.js-4.11.6.tgz",
 | 
				
			||||||
 | 
					      "integrity": "sha512-pqr857jrp2kPuO9uRjZ3PwnJTjoQy+fcdxvBTvHm6dkmEL9q+hDD/2j/0ELOBPtPnS8LjCX0gI9nbl8lVkadpg==",
 | 
				
			||||||
 | 
					      "dependencies": {
 | 
				
			||||||
 | 
					        "@types/node": "*"
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
    "node_modules/@types/body-parser": {
 | 
					    "node_modules/@types/body-parser": {
 | 
				
			||||||
      "version": "1.19.1",
 | 
					      "version": "1.19.1",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.1.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.1.tgz",
 | 
				
			||||||
@ -2096,6 +2105,53 @@
 | 
				
			|||||||
        "node": ">=10.4.0"
 | 
					        "node": ">=10.4.0"
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
					    "node_modules/bolt11": {
 | 
				
			||||||
 | 
					      "version": "1.3.4",
 | 
				
			||||||
 | 
					      "resolved": "https://registry.npmjs.org/bolt11/-/bolt11-1.3.4.tgz",
 | 
				
			||||||
 | 
					      "integrity": "sha512-x4lHDv0oid13lGlZU7cl/5gx9nRwjB2vgK/uB3c50802Wh+9WjWQMwzD2PCETHylUijx2iBAqUQYbx3ZgwF06Q==",
 | 
				
			||||||
 | 
					      "dependencies": {
 | 
				
			||||||
 | 
					        "@types/bn.js": "^4.11.3",
 | 
				
			||||||
 | 
					        "bech32": "^1.1.2",
 | 
				
			||||||
 | 
					        "bitcoinjs-lib": "^6.0.0",
 | 
				
			||||||
 | 
					        "bn.js": "^4.11.8",
 | 
				
			||||||
 | 
					        "create-hash": "^1.2.0",
 | 
				
			||||||
 | 
					        "lodash": "^4.17.11",
 | 
				
			||||||
 | 
					        "safe-buffer": "^5.1.1",
 | 
				
			||||||
 | 
					        "secp256k1": "^4.0.2"
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "node_modules/bolt11/node_modules/bech32": {
 | 
				
			||||||
 | 
					      "version": "1.1.4",
 | 
				
			||||||
 | 
					      "resolved": "https://registry.npmjs.org/bech32/-/bech32-1.1.4.tgz",
 | 
				
			||||||
 | 
					      "integrity": "sha512-s0IrSOzLlbvX7yp4WBfPITzpAU8sqQcpsmwXDiKwrG4r491vwCO/XpejasRNl0piBMe/DvP4Tz0mIS/X1DPJBQ=="
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "node_modules/bolt11/node_modules/bitcoinjs-lib": {
 | 
				
			||||||
 | 
					      "version": "6.0.1",
 | 
				
			||||||
 | 
					      "resolved": "https://registry.npmjs.org/bitcoinjs-lib/-/bitcoinjs-lib-6.0.1.tgz",
 | 
				
			||||||
 | 
					      "integrity": "sha512-x/7D4jDj/MMkmO6t3p2CSDXTqpwZ/jRsRiJDmaiXabrR9XRo7jwby8HRn7EyK1h24rKFFI7vI0ay4czl6bDOZQ==",
 | 
				
			||||||
 | 
					      "dependencies": {
 | 
				
			||||||
 | 
					        "bech32": "^2.0.0",
 | 
				
			||||||
 | 
					        "bip174": "^2.0.1",
 | 
				
			||||||
 | 
					        "bs58check": "^2.1.2",
 | 
				
			||||||
 | 
					        "create-hash": "^1.1.0",
 | 
				
			||||||
 | 
					        "typeforce": "^1.11.3",
 | 
				
			||||||
 | 
					        "varuint-bitcoin": "^1.1.2",
 | 
				
			||||||
 | 
					        "wif": "^2.0.1"
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      "engines": {
 | 
				
			||||||
 | 
					        "node": ">=8.0.0"
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "node_modules/bolt11/node_modules/bitcoinjs-lib/node_modules/bech32": {
 | 
				
			||||||
 | 
					      "version": "2.0.0",
 | 
				
			||||||
 | 
					      "resolved": "https://registry.npmjs.org/bech32/-/bech32-2.0.0.tgz",
 | 
				
			||||||
 | 
					      "integrity": "sha512-LcknSilhIGatDAsY1ak2I8VtGaHNhgMSYVxFrGLXv+xLHytaKZKcaUJJUE7qmBr7h33o5YQwP55pMI0xmkpJwg=="
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "node_modules/bolt11/node_modules/bn.js": {
 | 
				
			||||||
 | 
					      "version": "4.12.0",
 | 
				
			||||||
 | 
					      "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz",
 | 
				
			||||||
 | 
					      "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA=="
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
    "node_modules/boolbase": {
 | 
					    "node_modules/boolbase": {
 | 
				
			||||||
      "version": "1.0.0",
 | 
					      "version": "1.0.0",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz",
 | 
				
			||||||
@ -12218,6 +12274,14 @@
 | 
				
			|||||||
        "@types/node": "*"
 | 
					        "@types/node": "*"
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
					    "@types/bn.js": {
 | 
				
			||||||
 | 
					      "version": "4.11.6",
 | 
				
			||||||
 | 
					      "resolved": "https://registry.npmjs.org/@types/bn.js/-/bn.js-4.11.6.tgz",
 | 
				
			||||||
 | 
					      "integrity": "sha512-pqr857jrp2kPuO9uRjZ3PwnJTjoQy+fcdxvBTvHm6dkmEL9q+hDD/2j/0ELOBPtPnS8LjCX0gI9nbl8lVkadpg==",
 | 
				
			||||||
 | 
					      "requires": {
 | 
				
			||||||
 | 
					        "@types/node": "*"
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
    "@types/body-parser": {
 | 
					    "@types/body-parser": {
 | 
				
			||||||
      "version": "1.19.1",
 | 
					      "version": "1.19.1",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.1.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.1.tgz",
 | 
				
			||||||
@ -13215,6 +13279,54 @@
 | 
				
			|||||||
      "resolved": "https://registry.npmjs.org/bolt09/-/bolt09-0.1.5.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/bolt09/-/bolt09-0.1.5.tgz",
 | 
				
			||||||
      "integrity": "sha512-oT1+erg21vat55oXNd7nNEkCO0FQnmaraFZuyXFyeVk7dZCm/3vgic0qK1VuUSV+ksYXJfRKYC4AqfYrtHNPZg=="
 | 
					      "integrity": "sha512-oT1+erg21vat55oXNd7nNEkCO0FQnmaraFZuyXFyeVk7dZCm/3vgic0qK1VuUSV+ksYXJfRKYC4AqfYrtHNPZg=="
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
					    "bolt11": {
 | 
				
			||||||
 | 
					      "version": "1.3.4",
 | 
				
			||||||
 | 
					      "resolved": "https://registry.npmjs.org/bolt11/-/bolt11-1.3.4.tgz",
 | 
				
			||||||
 | 
					      "integrity": "sha512-x4lHDv0oid13lGlZU7cl/5gx9nRwjB2vgK/uB3c50802Wh+9WjWQMwzD2PCETHylUijx2iBAqUQYbx3ZgwF06Q==",
 | 
				
			||||||
 | 
					      "requires": {
 | 
				
			||||||
 | 
					        "@types/bn.js": "^4.11.3",
 | 
				
			||||||
 | 
					        "bech32": "^1.1.2",
 | 
				
			||||||
 | 
					        "bitcoinjs-lib": "^6.0.0",
 | 
				
			||||||
 | 
					        "bn.js": "^4.11.8",
 | 
				
			||||||
 | 
					        "create-hash": "^1.2.0",
 | 
				
			||||||
 | 
					        "lodash": "^4.17.11",
 | 
				
			||||||
 | 
					        "safe-buffer": "^5.1.1",
 | 
				
			||||||
 | 
					        "secp256k1": "^4.0.2"
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      "dependencies": {
 | 
				
			||||||
 | 
					        "bech32": {
 | 
				
			||||||
 | 
					          "version": "1.1.4",
 | 
				
			||||||
 | 
					          "resolved": "https://registry.npmjs.org/bech32/-/bech32-1.1.4.tgz",
 | 
				
			||||||
 | 
					          "integrity": "sha512-s0IrSOzLlbvX7yp4WBfPITzpAU8sqQcpsmwXDiKwrG4r491vwCO/XpejasRNl0piBMe/DvP4Tz0mIS/X1DPJBQ=="
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "bitcoinjs-lib": {
 | 
				
			||||||
 | 
					          "version": "6.0.1",
 | 
				
			||||||
 | 
					          "resolved": "https://registry.npmjs.org/bitcoinjs-lib/-/bitcoinjs-lib-6.0.1.tgz",
 | 
				
			||||||
 | 
					          "integrity": "sha512-x/7D4jDj/MMkmO6t3p2CSDXTqpwZ/jRsRiJDmaiXabrR9XRo7jwby8HRn7EyK1h24rKFFI7vI0ay4czl6bDOZQ==",
 | 
				
			||||||
 | 
					          "requires": {
 | 
				
			||||||
 | 
					            "bech32": "^2.0.0",
 | 
				
			||||||
 | 
					            "bip174": "^2.0.1",
 | 
				
			||||||
 | 
					            "bs58check": "^2.1.2",
 | 
				
			||||||
 | 
					            "create-hash": "^1.1.0",
 | 
				
			||||||
 | 
					            "typeforce": "^1.11.3",
 | 
				
			||||||
 | 
					            "varuint-bitcoin": "^1.1.2",
 | 
				
			||||||
 | 
					            "wif": "^2.0.1"
 | 
				
			||||||
 | 
					          },
 | 
				
			||||||
 | 
					          "dependencies": {
 | 
				
			||||||
 | 
					            "bech32": {
 | 
				
			||||||
 | 
					              "version": "2.0.0",
 | 
				
			||||||
 | 
					              "resolved": "https://registry.npmjs.org/bech32/-/bech32-2.0.0.tgz",
 | 
				
			||||||
 | 
					              "integrity": "sha512-LcknSilhIGatDAsY1ak2I8VtGaHNhgMSYVxFrGLXv+xLHytaKZKcaUJJUE7qmBr7h33o5YQwP55pMI0xmkpJwg=="
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "bn.js": {
 | 
				
			||||||
 | 
					          "version": "4.12.0",
 | 
				
			||||||
 | 
					          "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz",
 | 
				
			||||||
 | 
					          "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA=="
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
    "boolbase": {
 | 
					    "boolbase": {
 | 
				
			||||||
      "version": "1.0.0",
 | 
					      "version": "1.0.0",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz",
 | 
				
			||||||
 | 
				
			|||||||
@ -15,6 +15,7 @@
 | 
				
			|||||||
    "async-retry": "^1.3.1",
 | 
					    "async-retry": "^1.3.1",
 | 
				
			||||||
    "babel-plugin-inline-react-svg": "^2.0.1",
 | 
					    "babel-plugin-inline-react-svg": "^2.0.1",
 | 
				
			||||||
    "bech32": "^2.0.0",
 | 
					    "bech32": "^2.0.0",
 | 
				
			||||||
 | 
					    "bolt11": "^1.3.4",
 | 
				
			||||||
    "bootstrap": "^4.6.0",
 | 
					    "bootstrap": "^4.6.0",
 | 
				
			||||||
    "clipboard-copy": "^4.0.1",
 | 
					    "clipboard-copy": "^4.0.1",
 | 
				
			||||||
    "domino": "^2.1.6",
 | 
					    "domino": "^2.1.6",
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										128
									
								
								pages/satistics.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										128
									
								
								pages/satistics.js
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,128 @@
 | 
				
			|||||||
 | 
					import { useQuery } from '@apollo/client'
 | 
				
			||||||
 | 
					import Link from 'next/link'
 | 
				
			||||||
 | 
					import { Table } from 'react-bootstrap'
 | 
				
			||||||
 | 
					import useDarkMode from 'use-dark-mode'
 | 
				
			||||||
 | 
					import { getGetServerSideProps } from '../api/ssrApollo'
 | 
				
			||||||
 | 
					import Layout from '../components/layout'
 | 
				
			||||||
 | 
					import { useMe } from '../components/me'
 | 
				
			||||||
 | 
					import MoreFooter from '../components/more-footer'
 | 
				
			||||||
 | 
					import UserHeader from '../components/user-header'
 | 
				
			||||||
 | 
					import { WALLET_HISTORY } from '../fragments/wallet'
 | 
				
			||||||
 | 
					import styles from '../styles/satistics.module.css'
 | 
				
			||||||
 | 
					import Moon from '../svgs/moon-fill.svg'
 | 
				
			||||||
 | 
					import Check from '../svgs/check-double-line.svg'
 | 
				
			||||||
 | 
					import ThumbDown from '../svgs/thumb-down-fill.svg'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const getServerSideProps = getGetServerSideProps(WALLET_HISTORY)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function satusClass (status) {
 | 
				
			||||||
 | 
					  switch (status) {
 | 
				
			||||||
 | 
					    case 'CONFIRMED':
 | 
				
			||||||
 | 
					      return ''
 | 
				
			||||||
 | 
					    case 'PENDING':
 | 
				
			||||||
 | 
					      return 'text-muted'
 | 
				
			||||||
 | 
					    default:
 | 
				
			||||||
 | 
					      return styles.failed
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function Satus ({ status }) {
 | 
				
			||||||
 | 
					  if (!status) {
 | 
				
			||||||
 | 
					    return null
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const desc = () => {
 | 
				
			||||||
 | 
					    switch (status) {
 | 
				
			||||||
 | 
					      case 'CONFIRMED':
 | 
				
			||||||
 | 
					        return 'confirmed'
 | 
				
			||||||
 | 
					      case 'EXPIRED':
 | 
				
			||||||
 | 
					        return 'expired'
 | 
				
			||||||
 | 
					      case 'INSUFFICIENT_BALANCE':
 | 
				
			||||||
 | 
					        return "you didn't have enough sats"
 | 
				
			||||||
 | 
					      case 'INVALID_PAYMENT':
 | 
				
			||||||
 | 
					        return 'invalid payment'
 | 
				
			||||||
 | 
					      case 'PATHFINDING_TIMEOUT':
 | 
				
			||||||
 | 
					      case 'ROUTE_NOT_FOUND':
 | 
				
			||||||
 | 
					        return 'no route found'
 | 
				
			||||||
 | 
					      case 'PENDING':
 | 
				
			||||||
 | 
					        return 'pending'
 | 
				
			||||||
 | 
					      default:
 | 
				
			||||||
 | 
					        return 'unknown failure'
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const color = () => {
 | 
				
			||||||
 | 
					    switch (status) {
 | 
				
			||||||
 | 
					      case 'CONFIRMED':
 | 
				
			||||||
 | 
					        return 'success'
 | 
				
			||||||
 | 
					      case 'PENDING':
 | 
				
			||||||
 | 
					        return 'muted'
 | 
				
			||||||
 | 
					      default:
 | 
				
			||||||
 | 
					        return 'danger'
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const Icon = () => {
 | 
				
			||||||
 | 
					    switch (status) {
 | 
				
			||||||
 | 
					      case 'CONFIRMED':
 | 
				
			||||||
 | 
					        return <Check width='14' height='14' className='fill-success' />
 | 
				
			||||||
 | 
					      case 'PENDING':
 | 
				
			||||||
 | 
					        return <Moon width='14' height='14' className='spin fill-grey' />
 | 
				
			||||||
 | 
					      default:
 | 
				
			||||||
 | 
					        return <ThumbDown width='14' height='14' className='fill-danger' />
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return (
 | 
				
			||||||
 | 
					    <div>
 | 
				
			||||||
 | 
					      <Icon /><small className={`text-${color()}`}>{' ' + desc()}</small>
 | 
				
			||||||
 | 
					    </div>
 | 
				
			||||||
 | 
					  )
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default function Satistics ({ data: { walletHistory: { facts, cursor } } }) {
 | 
				
			||||||
 | 
					  const me = useMe()
 | 
				
			||||||
 | 
					  const { value: darkMode } = useDarkMode()
 | 
				
			||||||
 | 
					  const { data, fetchMore } = useQuery(WALLET_HISTORY)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (data) {
 | 
				
			||||||
 | 
					    ({ walletHistory: { facts, cursor } } = data)
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const SatisticsSkeleton = () => (
 | 
				
			||||||
 | 
					    <div className='d-flex justify-content-center mt-3 mb-1'>
 | 
				
			||||||
 | 
					      <Moon className='spin fill-grey' />
 | 
				
			||||||
 | 
					    </div>)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return (
 | 
				
			||||||
 | 
					    <Layout noSeo>
 | 
				
			||||||
 | 
					      <UserHeader user={me} />
 | 
				
			||||||
 | 
					      <Table className='mt-3 mb-0' bordered hover size='sm' variant={darkMode ? 'dark' : undefined}>
 | 
				
			||||||
 | 
					        <thead>
 | 
				
			||||||
 | 
					          <tr>
 | 
				
			||||||
 | 
					            <th className={styles.type}>type</th>
 | 
				
			||||||
 | 
					            <th>detail</th>
 | 
				
			||||||
 | 
					            <th className={styles.sats}>sats</th>
 | 
				
			||||||
 | 
					          </tr>
 | 
				
			||||||
 | 
					        </thead>
 | 
				
			||||||
 | 
					        <tbody>
 | 
				
			||||||
 | 
					          {facts.map((f, i) => (
 | 
				
			||||||
 | 
					            <Link href={`${f.type}s/${f.id}`} key={`${f.type}-${f.id}`}>
 | 
				
			||||||
 | 
					              <tr className={styles.row}>
 | 
				
			||||||
 | 
					                <td className={`${styles.type} ${satusClass(f.status)}`}>{f.type}</td>
 | 
				
			||||||
 | 
					                <td className={styles.description}>
 | 
				
			||||||
 | 
					                  <div className={satusClass(f.status)}>
 | 
				
			||||||
 | 
					                    {f.description || 'no description'}
 | 
				
			||||||
 | 
					                  </div>
 | 
				
			||||||
 | 
					                  <Satus status={f.status} />
 | 
				
			||||||
 | 
					                </td>
 | 
				
			||||||
 | 
					                <td className={`${styles.sats} ${satusClass(f.status)}`}>{f.msats / 1000}</td>
 | 
				
			||||||
 | 
					              </tr>
 | 
				
			||||||
 | 
					            </Link>
 | 
				
			||||||
 | 
					          ))}
 | 
				
			||||||
 | 
					        </tbody>
 | 
				
			||||||
 | 
					      </Table>
 | 
				
			||||||
 | 
					      <MoreFooter cursor={cursor} fetchMore={fetchMore} Skeleton={SatisticsSkeleton} />
 | 
				
			||||||
 | 
					    </Layout>
 | 
				
			||||||
 | 
					  )
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -59,6 +59,20 @@ $tooltip-bg: #5c8001;
 | 
				
			|||||||
  src: url(/Lightningvolt-xoqm.ttf);
 | 
					  src: url(/Lightningvolt-xoqm.ttf);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.table-sm th, .table-sm td {
 | 
				
			||||||
 | 
					  padding: .3rem .75rem;
 | 
				
			||||||
 | 
					  line-height: 1.2rem;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.table {
 | 
				
			||||||
 | 
					  color: var(--theme-color);
 | 
				
			||||||
 | 
					  background-color: var(--theme-body);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.table th, .table td, .table thead th {
 | 
				
			||||||
 | 
					  border-color: var(--theme-borderColor);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
body {
 | 
					body {
 | 
				
			||||||
  background: var(--theme-body);
 | 
					  background: var(--theme-body);
 | 
				
			||||||
  color: var(--theme-color);
 | 
					  color: var(--theme-color);
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										18
									
								
								styles/satistics.module.css
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								styles/satistics.module.css
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,18 @@
 | 
				
			|||||||
 | 
					.type {
 | 
				
			||||||
 | 
					    width: 1px;
 | 
				
			||||||
 | 
					    white-space: nowrap;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.sats {
 | 
				
			||||||
 | 
					    width: 1px;
 | 
				
			||||||
 | 
					    white-space: nowrap;
 | 
				
			||||||
 | 
					    text-align: right;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.failed {
 | 
				
			||||||
 | 
					    text-decoration: line-through;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.row {
 | 
				
			||||||
 | 
					    cursor: pointer;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user