# Automated Invoicing > Current PR: https://github.com/Holo-Host/servicelogger-rsm The role of servicelogger is an internal Holo component that measures and logs the hosting activity carried out by a Host on behalf of the Holo web-clients and periodically generates a proof of service invoice based on the Host's preference settings via a bridge to Holofuel. Servicelogger triggers an invoice when the `log_activity` endpoint is called and the sum of all logs creates an invoice value that is equal to or greater than the `max_fuel_before_invoice` preferences set by the host. If these preference conditions are met, then SL will automatically trigger the call to the `create_invoice` in HF. Here is the payload for generating an invoice in HoloFuel: ```rust= struct InvoiceInput { spender: AgentPubKeyB64, amount: String, note: Option<String>, proof_of_service_token: Option<CapSecret>, url: Option<String>, promise: Option<EntryHash>, } ``` > Where the value of Note =`Holo Hosting Invoice <last 5 char of hha_id>: <hApp_name>` See here for more info: https://chat.holochain.org/holo/pl/aahi4s9fwb897d34qmcqiwhzky Questions: - Should commit an invoice with a notes field that contains the happ hha hash and happ name, or only commit with the happ hha hash and make the call to fetch the happ name associated with the happ hha hash at the client level? - Do we also want to trigger the automated invoice whenever the`max_time_before_invoice` preference setting has been met? To-date this has been unimplmented and mentioned as OOS. If we don't decide to implement, when is the ideal time for this? - If we are unable to call the cell locally, and unable to call into cells from other happs - how do we want to manage passing the cell id? - ~~Decision is to bundle SL, HF, and HHA DNAs together as single core happ~~ Decision is to keep as separate happ bundles for now. We've tested out the bridging call between two separate happs, and this is still allowed by holochain atm. Resources: - HF Repo: https://github.com/Holo-Host/holofuel - SL Repo: https://github.com/Holo-Host/servicelogger-rsm - MM channel re: notes: [link to convo](https://chat.holochain.org/holo/channels/tmparch-holofuel-transaction-payload) --- #### TODO Checklist: Lisa: - [x] maintain two separate happs in tests - [x] ping pj for review Pj: - [x] resolve CI issue - [x] review - [ ] updates to hpos-holochain-api - /earnings ## UI Questions ### Earnings view: - Is the value of "Weekly Earnings" equal to "Dashboard" -> "Last 7 days" earnings, if not, where can we get the value from? Weekly Earning should be equal to - "last 7 days based on UTC for now", confirm with Lisa that this is the value in the dashboard. - A: The interval is set for the past 7 days. Timestamps are not stored as UTC, however. They are an interger showing the microseconds elapsed since January 1 & stored as a u64. ### Paid / Unpaid invoices: - Q: What is the value of "Available Balance" and where can we take it from? - A: Can take if from the `/audit_my_chain` endpoint, which returns the `available` balance already calculated #### Invoices data: ##### Requirements: - data will be consumed as an Array of objects ``` { hAppName: string publishedBy: String (agent address should be converted to Uint8Array to generate Identicon) created: string | Date object ??? - No, it is not a date object. It is a date.now() equivalent from rust, but in microseconds and returned as a string due: string | Date object ??? (system default for this initiative)- type is same as created value above transactionHash: string amount: number status: string (paid or unpaid for this initiative) } ``` - data should be paginated (page number selected via UI) - data should be returned in batches (per page value selected via UI) - data should be sorted (ASC/DESC) by one of the values (selected via UI) - hAppName - publishedBy - createdDate - dueDate - transactionHash - amount - status - no filtering in this initiative #### Paid Invoices Object returned by the `holofuel/transactor/get_completed_transactions` zome_call ``` pub struct Transaction { pub id: EntryHashB64, pub amount: String, pub created_date: Timestamp, pub completed_date: Option<Timestamp>, pub transaction_type: TransactionType, pub counterparty: AgentPubKeyB64, pub direction: TransactionDirection, pub status: TransactionStatus, pub note: Option<String>, pub proof_of_service_token: Option<CapSecret>, pub url: Option<String>, pub expiration_date: Option<Timestamp>, } ``` Fields mapping for FE: ``` hAppName => extracted from note -- YES publishedBy => counterparty?? -- YES createdDate => created_date (what format?) -- i64 > in microseconds dueDate => expiration_date?? -- YES. transactionHash => id amount => amount (string?) -- YES, it is a string. All numbers are returned as strings to avoid any of the funky number calcuations and double floats that js does. status => fixed string (paid or unpaid for this initiative) -- an enum type ``` ##### Clarification needed - hAppName - example format of the note required for the extraction logic purposes - publishedBy - is this field equal to counterparty returned by the zome call? - Yes. - createdDate - what is the exact format of "Timestamp"? - string that was stored as a integer and evaluated as number of microseconds since 1970. - dueDate - is it expiration_date? - Yes. - amount - should this be returned as a String? - Yes. All numbers are returned as strings to avoid any of the funky number calcuations and double floats that javascript does. Celestial - should we show Due Date for completed transactions, it sounds more resonable to show completed_date - IDEA: Maybe show both what the expiration date was as well when it was completed. These would have different value/meaning for business analytics, evaluations, etc. #### Unpaid Invoices Object returned by the `holofuel/transactor/get_pending_transactions` zome_call The function returns an object with following types of transactions ``` { accepted: [] invoice_declined: [] invoice_pending: [] promise_declined: [] promise_pending: [] } ``` We need clarification: - What are those sets? - These are all lists of `Transaction` structs. - Below is what a `Transaction` and its substructures look like: ```rust pub struct Timestamp(pub i64) pub enum TransactionDirection { Outgoing, Incoming, } pub enum TransactionStatus { Actionable, Pending, Accepted, Completed, Declined, Expired, } pub struct Transaction { pub id: EntryHashB64, pub amount: String, pub created_date: Timestamp, pub completed_date: Option<Timestamp>, pub transaction_type: TransactionType, pub counterparty: AgentPubKeyB64, pub direction: TransactionDirection, pub status: TransactionStatus, pub note: Option<String>, pub proof_of_service_token: Option<CapSecret>, pub url: Option<String>, pub expiration_date: Option<Timestamp>, } ``` - Is the structure of each set item the same? What is the structure of those items? - Yes, each of these return a list of Transaction types - What happens between the moment the transaction is accepted and moment when the transaction is completed? How long does it take? - The transaction needs to be countersigned. This is a variable amount of time, therefore we cannot set expectations in the UI around the time it will take to complete the tx beyond that a completed transaction requires the countersigning. - What is the difference between "invoice_" and "promise_"? - `promise` is something that has been offered and will be debited from the balance once the coutnerparty accepts and countersigns - `invoice` is something that has been requested and will be credited to the balance once the counterparty accepts and countersigns - Which sets should be visible in the "unpaid" invoices table? Should "accepted" be included in "unpaid" invoices? - We should check with C. I think there might be a separate section for declined and accepted/awaiting completion. #### Definitions: - Actionable = tx that was created by 1st instance and waiting for counterparty to complete the tx - Pending = tx that was created by 1st instance and second instance - Accepted = tx that was accepted by counterparty but has yet to complete countersigning ##### Example Return Value for Completed and Pending Endpoints: - `get_completed_transactions` ``` [ { id: 'uhCEkuoMG0RpLkYciC3ZO2ZiedEhDq9yZJLrbjjVmNmXvjpvaAE6H', amount: '3.23', created_date: 1663689359833559, completed_date: null, transaction_type: { Request: null }, counterparty: 'uhCAki0d39_k2EkZzuUESiw03zuRYoPh05vswcLsi566MC-Nxqtuc', direction: { Outgoing: null }, status: { Completed: null }, note: 'Holo Hosting Invoice <last 5 char of hha_id>: <hApp_name>', proof_of_service_token: null, url: null, expiration_date: null } ] ``` - `get_pending_transactions` ``` { invoice_pending: [ { id: 'uhCEk8JMlpIf-ITDT7uND_zvyGG2hp6VhnYzG6WUpwOxF6ya8105V', amount: '3.23', created_date: 1663688288937268, completed_date: null, transaction_type: { Request: null }, counterparty: 'uhCAkDOc0jde0SS4CO3HRThx5_cee2Nm_w-T30bTNE-uLmMoOoZzX', direction: { Outgoing: null }, status: { Pending: null }, note: 'Holo Hosting Invoice <last 5 char of hha_id>: <hApp_name>', proof_of_service_token: null, url: null, expiration_date: null } ], promise_pending: [ { id: 'uhCEkoQQJ2Ksp_FcqEnatDYBLFQzzWzStQdXE5SDDI4a2rqZyh7ik', amount: '1.23', created_date: 1663688288964525, completed_date: null, transaction_type: { Offer: null }, counterparty: 'uhCAkDOc0jde0SS4CO3HRThx5_cee2Nm_w-T30bTNE-uLmMoOoZzX', direction: { Outgoing: null }, status: { Pending: null }, note: 'Holo Hosting Invoice <last 5 char of hha_id>: <hApp_name>', proof_of_service_token: null, url: null, expiration_date: 9007199254740991 } ], invoice_declined: [], promise_declined: [], accepted: [] } ```